<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!--[if lt IE 9]>
  <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<![endif]-->
<title>VIM 中文帮助: 键盘映射及缩写</title>
<link rel="stylesheet" href="vim-stylesheet.css" type="text/css" />
<link rel="canonical" href="https://yianwillis.github.io/vimcdoc/doc/map.html" />
<script type="text/javascript" src="vimcdoc.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<nav id=banner>
<form action=tags.html target="tag_iframe">
  <input type="text" name="tag" id="tag" placeholder="标签搜索">
</form>
<iframe name="tag_iframe" src=""></iframe>
<a href="help.html">帮助总览</a> &middot;
<hr/>
<a href="quickref.html">快速参考</a> &middot;
<a href="index.html">命令索引</a> &middot;
<a href="eval.html#functions">函数列表</a> &middot;
<a href="quickref.html#option-list">选项列表</a> &middot;
<hr/>
<a href="usr_toc.html">用户手册</a> &middot;
<a href="help.html#reference_toc">参考手册</a> &middot;
</nav>

<header>
<h2>map</h2>
</header>
<article id=outer>
<section class=inner>
<b class="vimtag"> <a name="map.txt">map.txt</a> </b>       适用于 Vim 9.0 版本。   最近更新: 2023年2月


                  <code class="vim">VIM 参考手册    by Bram Moolenaar</code>
                                <code class="vim">译者</code>: con&lt;con@netease.com&gt;


键映射、缩写和用户定义的命令。

本主题在用户手册  <a href="usr_05.html#05.4">05.4</a> ， <a href="usr_24.html#24.7">24.7</a>  和  <a href="usr_40.html#40.1">40.1</a>  中有过介绍。

1. 键映射                        <a href="map.html#key-mapping">key-mapping</a> 
   1.1 映 射 命 令                               <a href="map.html#:map-commands">:map-commands</a> 
   1.2 特殊参数                                  <a href="map.html#:map-arguments">:map-arguments</a> 
   1.3 映射与运行模式                            <a href="map.html#:map-modes">:map-modes</a> 
   1.4 列出映射                                  <a href="map.html#map-listing">map-listing</a> 
   1.5 映射特殊键                                <a href="map.html#:map-special-keys">:map-special-keys</a> 
   1.6 特殊字符                                  <a href="map.html#:map-special-chars">:map-special-chars</a> 
   1.7 映射哪些键                                <a href="map.html#map-which-keys">map-which-keys</a> 
   1.8 示例                                      <a href="map.html#map-examples">map-examples</a> 
   1.9 使用映射                                  <a href="map.html#map-typing">map-typing</a> 
   1.10 映射 ALT 键                              <a href="map.html#:map-alt-keys">:map-alt-keys</a> 
   1.11 映射 META 键                             <a href="map.html#:map-meta-keys">:map-meta-keys</a> 
   1.12 modifyOtherKeys 模式映射                 <a href="map.html#modifyOtherKeys">modifyOtherKeys</a> 
   1.13 使用 Kitty 键盘协议的映射                <a href="map.html#kitty-keyboard-protocol">kitty-keyboard-protocol</a> 
   1.14 映射操作符                               <a href="map.html#:map-operator">:map-operator</a> 
2. 缩写                          <a href="map.html#abbreviations">abbreviations</a> 
3. 局部映射和函数                <a href="map.html#script-local">script-local</a> 
4. 用户定义的命令                <a href="map.html#user-commands">user-commands</a> 

</section><hr class="doubleline" /><section class=inner>
<h4>1. 键映射                               <b class="vimtag"> <a name="key-mapping">key-mapping</a> </b> <b class="vimtag"> <a name="mapping">mapping</a> </b> <b class="vimtag"> <a name="macro">macro</a> </b></h4>
键映射用于改变输入键的含义。最常见的用途是把功能键定义为一系列的命令。比如: 
<code class="example"></code>
<code class="example">        :map &lt;F2&gt; a&lt;C-R&gt;=strftime("%c")&lt;CR&gt;&lt;Esc&gt;</code>
<code class="example"></code>
这个映射会在光标之后追加当前的日期和时间 (用 <code class="special">&lt;&gt;</code> 记法  <a href="intro.html#%3C%3E">&lt;&gt;</a> )。


1.1 映 射 命 令                                         <b class="vimtag"> <a name=":map-commands">:map-commands</a> </b>

有很多命令用于定义新的映射，删除映射和列出当前的映射。可以从  <a href="map.html#map-overview">map-overview</a>  参
考 "映射" 命令的不同形式及其与模式的关系。

<code class="special">{lhs}</code>   表示左手边      <b class="vimtag"> <a name="{lhs}">{lhs}</a> </b>
<code class="special">{rhs}</code>   表示右手边      <b class="vimtag"> <a name="{rhs}">{rhs}</a> </b>

:map    <code class="special">{lhs}</code> <code class="special">{rhs}</code>              <a href="map.html#mapmode-nvo">mapmode-nvo</a>            <b class="vimtag"> <a name=":map">:map</a> </b>
:nm[ap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>              <a href="map.html#mapmode-n">mapmode-n</a>              <b class="vimtag"> <a name=":nm">:nm</a> </b> <b class="vimtag"> <a name=":nmap">:nmap</a> </b>
:vm[ap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>              <a href="map.html#mapmode-v">mapmode-v</a>              <b class="vimtag"> <a name=":vm">:vm</a> </b> <b class="vimtag"> <a name=":vmap">:vmap</a> </b>
:xm[ap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>              <a href="map.html#mapmode-x">mapmode-x</a>              <b class="vimtag"> <a name=":xm">:xm</a> </b> <b class="vimtag"> <a name=":xmap">:xmap</a> </b>
:smap   <code class="special">{lhs}</code> <code class="special">{rhs}</code>              <a href="map.html#mapmode-s">mapmode-s</a>                  <b class="vimtag"> <a name=":smap">:smap</a> </b>
:om[ap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>              <a href="map.html#mapmode-o">mapmode-o</a>              <b class="vimtag"> <a name=":om">:om</a> </b> <b class="vimtag"> <a name=":omap">:omap</a> </b>
:map!   <code class="special">{lhs}</code> <code class="special">{rhs}</code>              <a href="map.html#mapmode-ic">mapmode-ic</a>             <b class="vimtag"> <a name=":map!">:map!</a> </b>
:im[ap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>              <a href="map.html#mapmode-i">mapmode-i</a>              <b class="vimtag"> <a name=":im">:im</a> </b> <b class="vimtag"> <a name=":imap">:imap</a> </b>
:lm[ap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>              <a href="map.html#mapmode-l">mapmode-l</a>              <b class="vimtag"> <a name=":lm">:lm</a> </b> <b class="vimtag"> <a name=":lma">:lma</a> </b> <b class="vimtag"> <a name=":lmap">:lmap</a> </b>
:cm[ap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>              <a href="map.html#mapmode-c">mapmode-c</a>              <b class="vimtag"> <a name=":cm">:cm</a> </b> <b class="vimtag"> <a name=":cmap">:cmap</a> </b>
:tma[p] <code class="special">{lhs}</code> <code class="special">{rhs}</code>              <a href="map.html#mapmode-t">mapmode-t</a>              <b class="vimtag"> <a name=":tma">:tma</a> </b> <b class="vimtag"> <a name=":tmap">:tmap</a> </b>
                        在映射命令作用的模式中把键系列 <code class="special">{lhs}</code> 映射为 <code class="special">{rhs}</code>。并
                        且映射后的 <code class="special">{rhs}</code> 也被进行映射扫描。这个特性可以用来进
                        行映射的嵌套和递归。
                        <code class="note">注意</code>: <code class="special">{rhs}</code> 包含拖尾空格，因为空格是合法的普通模式命
                        令。见  <a href="map.html#map-trailing-white">map-trailing-white</a> 。

                                                <b class="vimtag"> <a name=":nore">:nore</a> </b> <b class="vimtag"> <a name=":norem">:norem</a> </b>
:no[remap]  <code class="special">{lhs}</code> <code class="special">{rhs}</code>          <a href="map.html#mapmode-nvo">mapmode-nvo</a>    <b class="vimtag"> <a name=":no">:no</a> </b>  <b class="vimtag"> <a name=":noremap">:noremap</a> </b> <b class="vimtag"> <a name=":nor">:nor</a> </b>
:nn[oremap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>          <a href="map.html#mapmode-n">mapmode-n</a>      <b class="vimtag"> <a name=":nn">:nn</a> </b>  <b class="vimtag"> <a name=":nnoremap">:nnoremap</a> </b>
:vn[oremap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>          <a href="map.html#mapmode-v">mapmode-v</a>      <b class="vimtag"> <a name=":vn">:vn</a> </b>  <b class="vimtag"> <a name=":vnoremap">:vnoremap</a> </b>
:xn[oremap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>          <a href="map.html#mapmode-x">mapmode-x</a>      <b class="vimtag"> <a name=":xn">:xn</a> </b>  <b class="vimtag"> <a name=":xnoremap">:xnoremap</a> </b>
:snor[emap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>          <a href="map.html#mapmode-s">mapmode-s</a>      <b class="vimtag"> <a name=":snor">:snor</a> </b> <b class="vimtag"> <a name=":snore">:snore</a> </b> <b class="vimtag"> <a name=":snoremap">:snoremap</a> </b>
:ono[remap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>          <a href="map.html#mapmode-o">mapmode-o</a>      <b class="vimtag"> <a name=":ono">:ono</a> </b> <b class="vimtag"> <a name=":onoremap">:onoremap</a> </b>
:no[remap]! <code class="special">{lhs}</code> <code class="special">{rhs}</code>          <a href="map.html#mapmode-ic">mapmode-ic</a>     <b class="vimtag"> <a name=":no!">:no!</a> </b> <b class="vimtag"> <a name=":noremap!">:noremap!</a> </b>
:ino[remap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>          <a href="map.html#mapmode-i">mapmode-i</a>      <b class="vimtag"> <a name=":ino">:ino</a> </b> <b class="vimtag"> <a name=":inor">:inor</a> </b> <b class="vimtag"> <a name=":inoremap">:inoremap</a> </b>
:ln[oremap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>          <a href="map.html#mapmode-l">mapmode-l</a>      <b class="vimtag"> <a name=":ln">:ln</a> </b>  <b class="vimtag"> <a name=":lnoremap">:lnoremap</a> </b>
:cno[remap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>          <a href="map.html#mapmode-c">mapmode-c</a>      <b class="vimtag"> <a name=":cno">:cno</a> </b> <b class="vimtag"> <a name=":cnor">:cnor</a> </b> <b class="vimtag"> <a name=":cnoremap">:cnoremap</a> </b>
:tno[remap] <code class="special">{lhs}</code> <code class="special">{rhs}</code>          <a href="map.html#mapmode-t">mapmode-t</a>      <b class="vimtag"> <a name=":tno">:tno</a> </b> <b class="vimtag"> <a name=":tnoremap">:tnoremap</a> </b>
                        在映射命令作用的模式中把键序列 <code class="special">{lhs}</code> 映射为 <code class="special">{rhs}</code> 。禁
                        止对映射后的 <code class="special">{rhs}</code> 进行映射扫描。这个特性可以避免映射
                        的嵌套和递归。通常用于重定义一个命令。
                        <code class="note">注意</code>: <code class="special">&lt;Plug&gt;</code> 出现在 <code class="special">{rhs}</code> 时，总会被应用，即使不允许重
                        映射也是如此。

:unm[ap]  <code class="special">{lhs}</code>                  <a href="map.html#mapmode-nvo">mapmode-nvo</a>            <b class="vimtag"> <a name=":unm">:unm</a> </b>  <b class="vimtag"> <a name=":unmap">:unmap</a> </b>
:nun[map] <code class="special">{lhs}</code>                  <a href="map.html#mapmode-n">mapmode-n</a>              <b class="vimtag"> <a name=":nun">:nun</a> </b>  <b class="vimtag"> <a name=":nunmap">:nunmap</a> </b>
:vu[nmap] <code class="special">{lhs}</code>                  <a href="map.html#mapmode-v">mapmode-v</a>              <b class="vimtag"> <a name=":vu">:vu</a> </b>   <b class="vimtag"> <a name=":vunmap">:vunmap</a> </b>
:xu[nmap] <code class="special">{lhs}</code>                  <a href="map.html#mapmode-x">mapmode-x</a>              <b class="vimtag"> <a name=":xu">:xu</a> </b>   <b class="vimtag"> <a name=":xunmap">:xunmap</a> </b>
:sunm[ap] <code class="special">{lhs}</code>                  <a href="map.html#mapmode-s">mapmode-s</a>              <b class="vimtag"> <a name=":sunm">:sunm</a> </b> <b class="vimtag"> <a name=":sunmap">:sunmap</a> </b>
:ou[nmap] <code class="special">{lhs}</code>                  <a href="map.html#mapmode-o">mapmode-o</a>              <b class="vimtag"> <a name=":ou">:ou</a> </b>   <b class="vimtag"> <a name=":ounmap">:ounmap</a> </b>
:unm[ap]! <code class="special">{lhs}</code>                  <a href="map.html#mapmode-ic">mapmode-ic</a>             <b class="vimtag"> <a name=":unm!">:unm!</a> </b> <b class="vimtag"> <a name=":unmap!">:unmap!</a> </b>
:iu[nmap] <code class="special">{lhs}</code>                  <a href="map.html#mapmode-i">mapmode-i</a>              <b class="vimtag"> <a name=":iu">:iu</a> </b>   <b class="vimtag"> <a name=":iunmap">:iunmap</a> </b>
:lu[nmap] <code class="special">{lhs}</code>                  <a href="map.html#mapmode-l">mapmode-l</a>              <b class="vimtag"> <a name=":lu">:lu</a> </b>   <b class="vimtag"> <a name=":lunmap">:lunmap</a> </b>
:cu[nmap] <code class="special">{lhs}</code>                  <a href="map.html#mapmode-c">mapmode-c</a>              <b class="vimtag"> <a name=":cu">:cu</a> </b>   <b class="vimtag"> <a name=":cun">:cun</a> </b> <b class="vimtag"> <a name=":cunmap">:cunmap</a> </b>
:tunma[p] <code class="special">{lhs}</code>                  <a href="map.html#mapmode-t">mapmode-t</a>              <b class="vimtag"> <a name=":tunma">:tunma</a> </b> <b class="vimtag"> <a name=":tunmap">:tunmap</a> </b>
                        在映射命令作用的模式中删除 <code class="special">{lhs}</code> 的映射。该映射仍然可
                        以在其它模式中保留其定义。
                        即使映射的 <code class="special">{lhs}</code> 匹配 <code class="special">{rhs}</code> 也可以。缩写需要如此。
                        <code class="note">备注</code>: <code class="special">{lhs}</code> 包含拖尾的空格。见  <a href="map.html#map-trailing-white">map-trailing-white</a> 。

:mapc[lear]                      <a href="map.html#mapmode-nvo">mapmode-nvo</a>            <b class="vimtag"> <a name=":mapc">:mapc</a> </b>   <b class="vimtag"> <a name=":mapclear">:mapclear</a> </b>
:nmapc[lear]                     <a href="map.html#mapmode-n">mapmode-n</a>              <b class="vimtag"> <a name=":nmapc">:nmapc</a> </b>  <b class="vimtag"> <a name=":nmapclear">:nmapclear</a> </b>
:vmapc[lear]                     <a href="map.html#mapmode-v">mapmode-v</a>              <b class="vimtag"> <a name=":vmapc">:vmapc</a> </b>  <b class="vimtag"> <a name=":vmapclear">:vmapclear</a> </b>
:xmapc[lear]                     <a href="map.html#mapmode-x">mapmode-x</a>              <b class="vimtag"> <a name=":xmapc">:xmapc</a> </b>  <b class="vimtag"> <a name=":xmapclear">:xmapclear</a> </b>
:smapc[lear]                     <a href="map.html#mapmode-s">mapmode-s</a>              <b class="vimtag"> <a name=":smapc">:smapc</a> </b>  <b class="vimtag"> <a name=":smapclear">:smapclear</a> </b>
:omapc[lear]                     <a href="map.html#mapmode-o">mapmode-o</a>              <b class="vimtag"> <a name=":omapc">:omapc</a> </b>  <b class="vimtag"> <a name=":omapclear">:omapclear</a> </b>
:mapc[lear]!                     <a href="map.html#mapmode-ic">mapmode-ic</a>             <b class="vimtag"> <a name=":mapc!">:mapc!</a> </b>  <b class="vimtag"> <a name=":mapclear!">:mapclear!</a> </b>
:imapc[lear]                     <a href="map.html#mapmode-i">mapmode-i</a>              <b class="vimtag"> <a name=":imapc">:imapc</a> </b>  <b class="vimtag"> <a name=":imapclear">:imapclear</a> </b>
:lmapc[lear]                     <a href="map.html#mapmode-l">mapmode-l</a>              <b class="vimtag"> <a name=":lmapc">:lmapc</a> </b>  <b class="vimtag"> <a name=":lmapclear">:lmapclear</a> </b>
:cmapc[lear]                     <a href="map.html#mapmode-c">mapmode-c</a>              <b class="vimtag"> <a name=":cmapc">:cmapc</a> </b>  <b class="vimtag"> <a name=":cmapclear">:cmapclear</a> </b>
:tmapc[lear]                     <a href="map.html#mapmode-t">mapmode-t</a>              <b class="vimtag"> <a name=":tmapc">:tmapc</a> </b>  <b class="vimtag"> <a name=":tmapclear">:tmapclear</a> </b>
                        在映射命令作用的模式中删除 <code class="emphasis">所有</code> 的映射。
                        <code class="special">&lt;buffer&gt;</code> 参数可用来删除所的有缓冲区局部映射
                         <a href="map.html#:map-%3Cbuffer%3E">:map-&lt;buffer&gt;</a> 
                        <code class="note">警告</code>: 同时也会删除  <a href="os_mac.html#mac-standard-mappings">mac-standard-mappings</a>  和
                         <a href="os_dos.html#dos-standard-mappings">dos-standard-mappings</a> 。

:map                             <a href="map.html#mapmode-nvo">mapmode-nvo</a> 
:nm[ap]                          <a href="map.html#mapmode-n">mapmode-n</a> 
:vm[ap]                          <a href="map.html#mapmode-v">mapmode-v</a> 
:xm[ap]                          <a href="map.html#mapmode-x">mapmode-x</a> 
:sm[ap]                          <a href="map.html#mapmode-s">mapmode-s</a> 
:om[ap]                          <a href="map.html#mapmode-o">mapmode-o</a> 
:map!                            <a href="map.html#mapmode-ic">mapmode-ic</a> 
:im[ap]                          <a href="map.html#mapmode-i">mapmode-i</a> 
:lm[ap]                          <a href="map.html#mapmode-l">mapmode-l</a> 
:cm[ap]                          <a href="map.html#mapmode-c">mapmode-c</a> 
:tma[p]                          <a href="map.html#mapmode-t">mapmode-t</a> 
                        在映射命令作用的模式中列出所有的键映射。<code class="note">注意</code> ":map" 和
                        ":map!" 是最常用的，因为它们包括其它模式。

:map    <code class="special">{lhs}</code>                    <a href="map.html#mapmode-nvo">mapmode-nvo</a>            <b class="vimtag"> <a name=":map_l">:map_l</a> </b>
:nm[ap] <code class="special">{lhs}</code>                    <a href="map.html#mapmode-n">mapmode-n</a>              <b class="vimtag"> <a name=":nmap_l">:nmap_l</a> </b>
:vm[ap] <code class="special">{lhs}</code>                    <a href="map.html#mapmode-v">mapmode-v</a>              <b class="vimtag"> <a name=":vmap_l">:vmap_l</a> </b>
:xm[ap] <code class="special">{lhs}</code>                    <a href="map.html#mapmode-x">mapmode-x</a>              <b class="vimtag"> <a name=":xmap_l">:xmap_l</a> </b>
:sm[ap] <code class="special">{lhs}</code>                    <a href="map.html#mapmode-s">mapmode-s</a>              <b class="vimtag"> <a name=":smap_l">:smap_l</a> </b>
:om[ap] <code class="special">{lhs}</code>                    <a href="map.html#mapmode-o">mapmode-o</a>              <b class="vimtag"> <a name=":omap_l">:omap_l</a> </b>
:map!   <code class="special">{lhs}</code>                    <a href="map.html#mapmode-ic">mapmode-ic</a>             <b class="vimtag"> <a name=":map_l!">:map_l!</a> </b>
:im[ap] <code class="special">{lhs}</code>                    <a href="map.html#mapmode-i">mapmode-i</a>              <b class="vimtag"> <a name=":imap_l">:imap_l</a> </b>
:lm[ap] <code class="special">{lhs}</code>                    <a href="map.html#mapmode-l">mapmode-l</a>              <b class="vimtag"> <a name=":lmap_l">:lmap_l</a> </b>
:cm[ap] <code class="special">{lhs}</code>                    <a href="map.html#mapmode-c">mapmode-c</a>              <b class="vimtag"> <a name=":cmap_l">:cmap_l</a> </b>
:tma[p] <code class="special">{lhs}</code>                    <a href="map.html#mapmode-t">mapmode-t</a>              <b class="vimtag"> <a name=":tmap_l">:tmap_l</a> </b>
                        在映射命令作用的模式中列出以 <code class="special">{lhs}</code> 开头的键映射的键系
                        列。

这些命令用于把一个键或键系列映射成一个字符串。可以用来在功能键里放置一系列命
令，把一个键转换成另一个，等等。如何保存和恢复当前映射可以参考  <a href="starting.html#:mkexrc">:mkexrc</a> 。

                                                        <b class="vimtag"> <a name="map-ambiguous">map-ambiguous</a> </b>
当两个映射以相同的字符顺序开始，它们是有二义性的。例如: 
<code class="example">        :imap aa foo</code>
<code class="example">        :imap aaa bar</code>
当 Vim 读入 "aa" 后，它需要取得另外一个字符才能决定应该映射 "aa" 还是 "aaa"。
这意味着输入 "aa" 后映射还不会展开，Vim 还在等待另一个字符。如果你接着输入一个
空格，那么将插入 "foo" 加上空格。如果你输入一个 "a"，那么将插入 "bar"。

<code class="section">拖尾空格 </code>
                                                        <b class="vimtag"> <a name="map-trailing-white">map-trailing-white</a> </b>
此 unmap 命令 <code class="emphasis">不</code> 会成功: 
<code class="example">        :map @@ foo</code>
<code class="example">        :unmap @@ | print</code>
<code class="example"></code>
因为它试图删除映射 "@@ "，包含命令分隔符 "|" 之前的空格。其他一些有拖尾的空格
的例子: 
<code class="example">        unmap @@ </code>
<code class="example">        unmap @@     # Vim9 脚本注释</code>
<code class="example">        unmap @@     " 老式脚本注释</code>
<code class="example"></code>
会报错，但很难判断，因为 `unmap @@ ` 的拖尾空格是不可见的。

通用的解决方案是把命令分隔符 "|" 紧贴在映射键之后。之后就可以有空格和注释: 
<code class="example"></code>
<code class="example">        unmap @@|    # Vim9 脚本注释</code>
<code class="example">        unmap @@|    " 老式脚本注释</code>
<code class="example"></code>
<code class="example"></code>
1.2 特 殊 参 数                                         <b class="vimtag"> <a name=":map-arguments">:map-arguments</a> </b>

"<code class="special">&lt;buffer&gt;</code>"，"<code class="special">&lt;nowait&gt;</code>"，"<code class="special">&lt;silent&gt;</code>"，"<code class="special">&lt;special&gt;</code>"、"<code class="special">&lt;script&gt;</code>"、"<code class="special">&lt;expr&gt;</code>" 和
"<code class="special">&lt;unique&gt;</code>" 可以按任意顺序使用。它们必须紧跟在命令的后边，而在其它任何参数的前
边。

                                    <b class="vimtag"> <a name=":map-local">:map-local</a> </b> <b class="vimtag"> <a name=":map-%3Cbuffer%3E">:map-&lt;buffer&gt;</a> </b> <b class="vimtag"> <a name=":map-buffer">:map-buffer</a> </b>
                                    <b class="vimtag"> <a name="E224">E224</a> </b> <b class="vimtag"> <a name="E225">E225</a> </b>
如果这些命令的第一个参数是 "<code class="special">&lt;buffer&gt;</code>"，映射将只局限于当前的缓冲区内。例如: 
<code class="example">        :map &lt;buffer&gt;  ,w  /[.,;]&lt;CR&gt;</code>
然后你可以在另一个缓冲区内把 ",w" 作另外的映射: 
<code class="example">        :map &lt;buffer&gt;  ,w  /[#&amp;!]&lt;CR&gt;</code>
局部缓冲区映射在全局映射之前被应用。下面介绍的 <code class="special">&lt;nowait&gt;</code> 可以使一个较短的局部
映射在较长的全局映射存在时不起作用 (<code class="vim">译者注</code>: 此处或有误)。
"<code class="special">&lt;buffer&gt;</code>" 参数也可以用于清除映射: 
<code class="example">        :unmap &lt;buffer&gt; ,w</code>
<code class="example">        :mapclear &lt;buffer&gt;</code>
当一个缓冲区被删除时局部映射也会被清除，但是在它被卸载时不会。就像局部选项值的
情况一样。
另见  <a href="map.html#map-precedence">map-precedence</a> 。

                                                <b class="vimtag"> <a name=":map-%3Cnowait%3E">:map-&lt;nowait&gt;</a> </b> <b class="vimtag"> <a name=":map-nowait">:map-nowait</a> </b>
定义局部于缓冲区的映射 "," 时，可能有另一个全局映射也以 "," 开始。这时你需要
键入另一个字符，Vim 才能知道是用 "," 映射还是更长的那个。要避免这个问题，加入
<code class="special">&lt;nowait&gt;</code> 参数。这样映射一旦匹配就会被使用，Vim 不会等待更多字符的输入。但如果
那些字符已经输入了，还是会使用的。
<code class="note">注意</code>这里需要 <code class="special">&lt;nowait&gt;</code> 映射完整匹配且在任何部分匹配之前先找到。以下情形可以:
- 只有一个匹配的缓冲区局部映射，因为它们总在全局映射之前找到。
- 有另一个部分匹配的缓冲区局部映射，但在稍早前定义 (先找到最近定义的映射)。

                                                <b class="vimtag"> <a name=":map-%3Csilent%3E">:map-&lt;silent&gt;</a> </b> <b class="vimtag"> <a name=":map-silent">:map-silent</a> </b>
要在定义一个映射时不在命令行上回显该映射，可以使用 "<code class="special">&lt;silent&gt;</code>" 作为第一个参数，
例如: 
<code class="example">        :map &lt;silent&gt; ,h /Header&lt;CR&gt;</code>
在使用这个映射时搜索字串将不回显。不过被执行命令的信息仍然会。要把它也关掉，可
以在执行的命令里加入一个 ":silent": 
<code class="example">        :map &lt;silent&gt; ,h :exe ":silent normal /Header\r"&lt;CR&gt;</code>
<code class="note">注意</code> 命令的效果也可能被屏蔽，例如映射中如果选择了命令行补全的另一个项目，它不
会回显。
仍然会给出提示，比如使用 inputdialog() 的时候。
在缩写上使用 "<code class="special">&lt;silent&gt;</code>" 是可以的，但它的作用是使命令行不进行重绘。

                                                <b class="vimtag"> <a name=":map-%3Cspecial%3E">:map-&lt;special&gt;</a> </b> <b class="vimtag"> <a name=":map-special">:map-special</a> </b>
定义映射时，特殊键可用 <code class="special">&lt;&gt;</code> 记法，即使 <a href="options.html#'cpoptions'">'cpoptions'</a> 包含了 "&lt;" 标志位也没问题。这
可用于不希望看到设置 <a href="options.html#'cpoptions'">'cpoptions'</a> 时出现的副作用的场合。例如: 
<code class="example">        :map &lt;special&gt; &lt;F12&gt; /Header&lt;CR&gt;</code>

                                                <b class="vimtag"> <a name=":map-%3Cscript%3E">:map-&lt;script&gt;</a> </b> <b class="vimtag"> <a name=":map-script">:map-script</a> </b>
如果给用于定义新映射或缩写的命令的第一个参数是 "<code class="special">&lt;script&gt;</code>"，该映射只使用通过以
"<code class="special">&lt;SID&gt;</code>" 开头来定义的的脚本局部映射来重映射 <code class="special">{rhs}</code> 中的字符。这可以用于避免来自
外部的脚本的干扰 (举例来说，在 mswin.vim 中 <code class="keystroke">CTRL-V</code> 被重新映射的时候就是如此)，
但是又需要使用该脚本中定义的其它映射的情形。
<code class="note">备注</code>: ":map <code class="special">&lt;script&gt;</code>" 和 ":noremap <code class="special">&lt;script&gt;</code>" 做同样的事情。这里 "<code class="special">&lt;script&gt;</code>" 超
越命令名。不过，更推荐使用 ":noremap <code class="special">&lt;script&gt;</code>"，因为它更清晰地表示了重映射已被
(大多数时候) 禁止。

                                <b class="vimtag"> <a name=":map-%3Cunique%3E">:map-&lt;unique&gt;</a> </b> <b class="vimtag"> <a name=":map-unique">:map-unique</a> </b> <b class="vimtag"> <a name="E226">E226</a> </b> <b class="vimtag"> <a name="E227">E227</a> </b>
如果给用于定义新映射或缩写的命令的第一个参数是 "<code class="special">&lt;unique&gt;</code>" 并且它该映射或缩写已
经存在，则该命令会失败。例如: 
<code class="example">        :map &lt;unique&gt; ,w  /[#&amp;!]&lt;CR&gt;</code>
定义一个局部映射时，同时也会检查是否已存在了一个相同的全局映射。
这个例子将失败: 
<code class="example">        :map ,w  /[#&amp;!]&lt;CR&gt;</code>
<code class="example">        :map &lt;buffer&gt; &lt;unique&gt; ,w  /[.,;]&lt;CR&gt;</code>
如果你想给键进行映射，但同时又想执行原来映射的内容，参见  <a href="builtin.html#maparg()">maparg()</a> 。

                                                <b class="vimtag"> <a name=":map-%3Cexpr%3E">:map-&lt;expr&gt;</a> </b> <b class="vimtag"> <a name=":map-expression">:map-expression</a> </b>
如果给用于定义新映射或缩写的命令的第一个参数是 "<code class="special">&lt;expr&gt;</code>"，那么参数会作为表达式
来进行计算，结果作为实际使用的 <code class="special">{rhs}</code>。例如: 
<code class="example">        :inoremap &lt;expr&gt; . &lt;SID&gt;InsertDot()</code>
会插入 s:InsertDot() 函数的返回值。这可以用来检查光标之前的文本并在一定条件下
启动全能 (omni) 补全。建议使用局部于脚本的函数，以免污染全局命名空间。在 RHS
用 <code class="special">&lt;SID&gt;</code> 确保可以找到映射定义所在的脚本。

对于缩写， <a href="eval.html#v:char">v:char</a>  设为激活缩写的那个输入字符。你可以用它来决定如何扩展
<code class="special">{lhs}</code>。不能修改或插入 v:char。

如果你想映射不做任何事，可使表达式计算返回空串。如果有任何改变需要 Vim 走通主
循环 (例如刷新显示)，可返回 "\<code class="special">&lt;Ignore&gt;</code>"。这和 "nothing" 类似，但会使 Vim 从等
待输入的循环中返回。例如: 
<code class="example">        func s:OpenPopup()</code>
<code class="example">          call popup_create(... arguments ...)</code>
<code class="example">          return "\&lt;Ignore&gt;"</code>
<code class="example">        endfunc</code>
<code class="example">        nnoremap &lt;expr&gt; &lt;F3&gt; &lt;SID&gt;OpenPopup()</code>
<code class="example"></code>
记住前一个命令在等待预输入时，可能会在执行前进行表达式的计算。例如: 
<code class="example">        func StoreColumn()</code>
<code class="example">          let g:column = col('.')</code>
<code class="example">          return 'x'</code>
<code class="example">        endfunc</code>
<code class="example">        nnoremap &lt;expr&gt; x StoreColumn()</code>
<code class="example">        nmap ! f!x</code>
你会<code class="note">注意</code>到 g:colomn 保存了 "f!" 执行前的值，因为 "f!" 在执行前会先计算 "x"。要
解决这个问题，在表达式映射的那个字符前插入 <code class="special">&lt;Ignore&gt;</code>: 
<code class="example">        nmap ! f!&lt;Ignore&gt;x</code>
<code class="example"></code>
在  <a href="vim9.html#Vim9">Vim9</a>  脚本定义映射时，表达式的计算在该脚本的上下文进行。这意味着表达式可以
访问局部于脚本的项目。

要非常小心副作用！计算表达式的同时正在获取字符，因此很有可能你使得该命令不再可
用。为此原因禁止以下行为:
- 改变缓冲区文本  <a href="eval.html#textlock">textlock</a> 
- 编辑其它缓冲区
-  <a href="various.html#:normal">:normal</a>  命令
- 可以移动光标，但事后光标会被恢复
如果你希望通过映射来完成这些操作，让返回的字符做这些事情，或使用  <a href="map.html#%3CCmd%3E">&lt;Cmd&gt;</a>  映射
来代替。

你可以使用 getchar()，丢弃可能有的预输入。例如，如果有以下的映射: 
<code class="example">  inoremap &lt;expr&gt; &lt;C-L&gt; nr2char(getchar())</code>
<code class="example">  inoremap &lt;expr&gt; &lt;C-L&gt;x "foo"</code>
此时你如果输入 <code class="keystroke">CTRL-L</code>，什么都不会发生。Vim 需要下一个字符来决定采用哪个映射。
如果键入 'x'，采用第二个映射，插入 "foo"。如果键入其他字符，采用第一个映射，
getchar() 得到键入的字符并返回之。

这里是插入递增的列表编号的例子: 
<code class="example">        let counter = 0</code>
<code class="example">        inoremap &lt;expr&gt; &lt;C-L&gt; ListItem()</code>
<code class="example">        inoremap &lt;expr&gt; &lt;C-R&gt; ListReset()</code>
<code class="example"></code>
<code class="example">        func ListItem()</code>
<code class="example">          let g:counter += 1</code>
<code class="example">          return g:counter .. '. '</code>
<code class="example">        endfunc</code>
<code class="example"></code>
<code class="example">        func ListReset()</code>
<code class="example">          let g:counter = 0</code>
<code class="example">          return ''</code>
<code class="example">        endfunc</code>
<code class="example"></code>
<code class="keystroke">CTRL-L</code> 插入下一个数值，<code class="keystroke">CTRL-R</code> 复位计数且返回空字符串，这样就不会插入任何内容。

<code class="note">注意</code> 在其它文本之前使用单个字节出现的 0x80 是不行的。它会被看作一个特殊键。

                                                <b class="vimtag"> <a name="%3CCmd%3E">&lt;Cmd&gt;</a> </b> <b class="vimtag"> <a name=":map-cmd">:map-cmd</a> </b>
特殊文本 <code class="special">&lt;Cmd&gt;</code> 开始一种 "命令映射"，它直接执行命令而不切换模式。以前你在映射的
<code class="special">{rhs}</code> 可用 ": ...<code class="special">&lt;CR&gt;</code>" 的地方，现在可用 "<code class="special">&lt;Cmd&gt;</code>...<code class="special">&lt;CR&gt;</code>"。
示例: 
<code class="example">        noremap x &lt;Cmd&gt;echo mode(1)&lt;CR&gt;</code>

这比可视和操作符等待模式下的  <code class="badlink">:<code class="special">&lt;C-U&gt;</code></code> ，或插入模式下的  <code class="badlink"><code class="special">&lt;C-O&gt;</code>:</code>  更灵活，因为命
令在当前模式下直接执行，而不是总是进入普通模式。可视模式受到保护，因而不再需要
 <a href="visual.html#gv">gv</a>  的技巧。在命令行模式下直接执行命令 (否则，需要计时器这类的诀窍)。
例如要在插入方式半中间使用 <code class="special">&lt;Cmd&gt;</code>: 
<code class="example">        nnoremap &lt;F3&gt; aText &lt;Cmd&gt;echo mode(1)&lt;CR&gt; Added&lt;Esc&gt;</code>
<code class="example"></code>
和 <code class="special">&lt;expr&gt;</code> 映射不同，<code class="special">&lt;Cmd&gt;</code> 命令上没有特殊限制: 执行方式如同调用 (无限制的)
 <a href="autocmd.html#autocommand">autocommand</a> 。

                                                <b class="vimtag"> <a name="%3CScriptCmd%3E">&lt;ScriptCmd&gt;</a> </b>
<code class="special">&lt;ScriptCmd&gt;</code> 类似于 <code class="special">&lt;Cmd&gt;</code>，但命令执行期间，上下文设为映射定义所在的脚本。这对
 <a href="vim9.html#Vim9">Vim9</a>  脚本特别有用。也可用于访问导入，使用可能是自动载入的脚本的插件需要这一
点: 
<code class="example">        vim9script</code>
<code class="example">        import autoload 'implementation.vim' as impl</code>
<code class="example">        nnoremap &lt;F4&gt; &lt;ScriptCmd&gt;impl.DoTheWork()&lt;CR&gt;</code>
<code class="example"></code>
不管在哪里键入 <code class="special">&lt;F4&gt;</code>，"impl" 导入都能在映射定义所在的脚本的上下文可见。如果是自
动载入的导入，如此例所示，只在键入 <code class="special">&lt;F4&gt;</code> 时才载入 "implmentation.vim" 脚本，而
不是在映射定义的时候。

没有 <code class="special">&lt;ScriptCmd&gt;</code> 时，用 "s:impl" 会报告 "E121: Undefined variable"。

<code class="note">备注</code>:
- 既然 <code class="special">&lt;Cmd&gt;</code> 和 <code class="special">&lt;ScriptCmd&gt;</code> 避免了模式切换，就不触发  <a href="autocmd.html#CmdlineEnter">CmdlineEnter</a>  和
   <a href="autocmd.html#CmdlineLeave">CmdlineLeave</a>  事件，因为不期待用户互动。
- 同样原因，像 <code class="special">&lt;C-R&gt;</code><code class="special">&lt;C-W&gt;</code> 这样的  <a href="intro.html#keycodes">keycodes</a>  被解释为平凡的不经映射的键。
- 命令不回显，不需要 <code class="special">&lt;silent&gt;</code>。
- <code class="special">{rhs}</code> 不应用缩写或其他映射，即使映射是递归的也是。
- 可视模式里，可用  <code class="badlink">line('v')</code>  和  <code class="badlink">col('v')</code>  来得到可视区域的一角，光标则在另
  一角。

                                                        <b class="vimtag"> <a name="E1255">E1255</a> </b> <b class="vimtag"> <a name="E1136">E1136</a> </b>
<code class="special">&lt;Cmd&gt;</code> 和 <code class="special">&lt;ScriptCmd&gt;</code> 里的命令必须终止，亦即，在映射定义的 <code class="special">{rhs}</code> 里它们必须后跟
<code class="special">&lt;CR&gt;</code>。从不进入  <a href="cmdline.html#Command-line">Command-line</a>  模式。

                                                        <b class="vimtag"> <a name="E1137">E1137</a> </b>
<code class="special">&lt;Cmd&gt;</code> 和 <code class="special">&lt;ScriptCmd&gt;</code> 里的命令只能有普通字符，不能包含函数键这样的特殊字符。


1.3 映 射 与 运 行 模 式                                <b class="vimtag"> <a name=":map-modes">:map-modes</a> </b>
                        <b class="vimtag"> <a name="mapmode-nvo">mapmode-nvo</a> </b> <b class="vimtag"> <a name="mapmode-n">mapmode-n</a> </b> <b class="vimtag"> <a name="mapmode-v">mapmode-v</a> </b> <b class="vimtag"> <a name="mapmode-o">mapmode-o</a> </b>

有七种映射存在
- 用于普通模式: 输入命令时。
- 用于可视模式: 可视区域高亮并输入命令时。
- 用于选择模式: 类似于可视模式，但键入的字符对选择区进行替换。
- 用于操作符等待模式: 操作符等待中 ("d"，"y"，"c" 等等之后)。
  见下:  <a href="map.html#omap-info">omap-info</a> 。
- 用于插入模式: 也用于替换模式。
- 用于命令行模式: 输入 ":" 或 "/" 命令时。
- 用于终端模式: 在  <a href="terminal.html#:terminal">:terminal</a>  缓冲区里输入时。

特殊情况: 当在普通模式里为一个命令输入一个计数时，对 0 的映射会被禁用。这样在
输入一个带有 0 的计数时不会受到对 0 键映射的干扰。

                                                <b class="vimtag"> <a name="map-overview">map-overview</a> </b> <b class="vimtag"> <a name="map-modes">map-modes</a> </b>
关于每个映射命令对应的工作模式的概况。详情见下。
<code class="section">     命 令                       模 式 </code>
:map   :noremap  :unmap     普通、可视、选择、操作符等待
:nmap  :nnoremap :nunmap    普通
:vmap  :vnoremap :vunmap    可视与选择
:smap  :snoremap :sunmap    选择
:xmap  :xnoremap :xunmap    可视
:omap  :onoremap :ounmap    操作符等待
:map!  :noremap! :unmap!    插入与命令行
:imap  :inoremap :iunmap    插入
:lmap  :lnoremap :lunmap    插入、命令行、Lang-Arg
:cmap  :cnoremap :cunmap    命令行
:tmap  :tnoremap :tunmap    终端作业

同样的信息用表格总结一下:
                                                        <b class="vimtag"> <a name="map-table">map-table</a> </b>
<code class="section">         模式  | Norm | Ins | Cmd | Vis | Sel | Opr | Term | Lang | </code>
<code class="section">命令           +------+-----+-----+-----+-----+-----+------+------+ </code>
[nore]map      | yes  |  -  |  -  | yes | yes | yes |  -   |  -   |
n[nore]map     | yes  |  -  |  -  |  -  |  -  |  -  |  -   |  -   |
[nore]map!     |  -   | yes | yes |  -  |  -  |  -  |  -   |  -   |
i[nore]map     |  -   | yes |  -  |  -  |  -  |  -  |  -   |  -   |
c[nore]map     |  -   |  -  | yes |  -  |  -  |  -  |  -   |  -   |
v[nore]map     |  -   |  -  |  -  | yes | yes |  -  |  -   |  -   |
x[nore]map     |  -   |  -  |  -  | yes |  -  |  -  |  -   |  -   |
s[nore]map     |  -   |  -  |  -  |  -  | yes |  -  |  -   |  -   |
o[nore]map     |  -   |  -  |  -  |  -  |  -  | yes |  -   |  -   |
t[nore]map     |  -   |  -  |  -  |  -  |  -  |  -  | yes  |  -   |
l[nore]map     |  -   | yes | yes |  -  |  -  |  -  |  -   | yes  |


<code class="section">    命 令                                     模 式 </code>
<code class="section">                                        普通    可视+选择       操作符等待 </code>
:map   :noremap   :unmap   :mapclear    是      是              是
:nmap  :nnoremap  :nunmap  :nmapclear   是      -               -
:vmap  :vnoremap  :vunmap  :vmapclear   -       是              -
:omap  :onoremap  :ounmap  :omapclear   -       -               是

修道院之外也有 :nunmap (<code class="vim">译者注</code>: nun，修女)。
                                                <b class="vimtag"> <a name="mapmode-x">mapmode-x</a> </b> <b class="vimtag"> <a name="mapmode-s">mapmode-s</a> </b>
有的命令能同时用于可视和选择模式，有的只能用于其中一个。<code class="note">注意</code> 很常见的情况是提
到 "可视" 的时候实际同时适用可视和选择两种模式。 <a href="visual.html#Select-mode-mapping">Select-mode-mapping</a> 
<code class="note">备注</code>: 在选择模式映射可显示字符容易引起用户的混淆。最好直接用 :xmap 和 :smap 来
映射可显示字符。或者在定义映射后使用 :sunmap。

<code class="section">    命 令                                     模 式 </code>
<code class="section">                                        可视    选择 </code>
:vmap  :vnoremap  :vunmap  :vmapclear   是      是
:xmap  :xnoremap  :xunmap  :xmapclear   是      -
:smap  :snoremap  :sunmap  :smapclear   -       是

                        <b class="vimtag"> <a name="mapmode-ic">mapmode-ic</a> </b> <b class="vimtag"> <a name="mapmode-i">mapmode-i</a> </b> <b class="vimtag"> <a name="mapmode-c">mapmode-c</a> </b> <b class="vimtag"> <a name="mapmode-l">mapmode-l</a> </b>
有的命令同时支持插入模式和命令行模式，有的不是:

<code class="section">    命 令                                     模 式 </code>
<code class="section">                                        插入    命令行  Lang-Arg </code>
:map!  :noremap!  :unmap!  :mapclear!   是      是      -
:imap  :inoremap  :iunmap  :imapclear   是      -       -
:cmap  :cnoremap  :cunmap  :cmapclear   -       是      -
:lmap  :lnoremap  :lunmap  :lmapclear   是*     是*     是*

如果 <a href="options.html#'iminsert'">'iminsert'</a> 为 1，见下面的  <a href="map.html#language-mapping">language-mapping</a> 。

原来的 Vi 没有针对普通/可视/操作符等待模式和针对插入/命令行模式的独立映射。因
此 ":map" 和 ":map!" 命令为多个模式定义和回显映射。在 Vim 中你可以使用
":nmap"、":vmap"、:omap"、":cmap" 和 ":imap" 命令来对每个不同的模式分别定义映
射。

                                                        <b class="vimtag"> <a name="mapmode-t">mapmode-t</a> </b>
终端映射用于终端窗口中，其中输入的键用于终端中运行的作业。见
 <a href="terminal.html#terminal-typing">terminal-typing</a>  。

                                                        <b class="vimtag"> <a name="omap-info">omap-info</a> </b>
操作符等待映射可以用来定义和任何操作符一起使用的移动命令。简单例子: 
<code class="example">        :omap { w</code>
会使 "y{" 等同于 "yw"，"d{" 也等同于 "dw"。

要忽略光标原来所在的位置并选择另外的文本，你可以使 omap 进入可视模式来选择要操
作的文本。例如，要在位于当前行的函数名上操作: 
<code class="example">        onoremap &lt;silent&gt; F :&lt;C-U&gt;normal! 0f(hviw&lt;CR&gt;</code>
<code class="keystroke">CTRL-U</code> (<code class="special">&lt;C-U&gt;</code>) 用于删除命令行上 Vim 可能插入的范围。普通模式命令寻找第一个 '('
字符并选择之前的第一个单词。通常那就是函数名了。

要为普通和可视模式但不包括操作符等待模式输入一个映射，首先在所有的三个模式中定
义该映射，然后在操作符等待模式中取消该映射: 
<code class="example">        :map    xx something-difficult</code>
<code class="example">        :ounmap xx</code>
对于一个同时用于可视和操作符等待模式、或同时用于普通和操作符等待模式的映射也可
照此办理。

                                                <b class="vimtag"> <a name="language-mapping">language-mapping</a> </b>
":lmap" 定义一个应用于以下情况的映射:
- 插入模式
- 命令行模式
- 输入一个搜索模式时
- 接受一个文本字符作为参数的命令，比如 "r" 和 "f"
- 对于 input() 行
更一般地: 任何输入的字符是缓冲区文本的一部分而非一个 Vim 命令字符的时候。
"Lang-Arg" 不是真正的另外一个模式，它仅用来表示这些情况的存在。
   载入一个相关语言映射集合的最简单的方法是通过使用 <a href="options.html#'keymap'">'keymap'</a> 选项。
参考  <a href="usr_45.html#45.5">45.5</a> 。
   在插入模式和命令行模式中可用 <code class="keystroke">CTRL-^</code> 命令来关闭映射  <a href="insert.html#i_CTRL-^">i_CTRL-^</a>   <a href="cmdline.html#c_CTRL-^">c_CTRL-^</a> 。
这些命令改变 <a href="options.html#'iminsert'">'iminsert'</a> 选项的值。普通命令行 (非模式搜索) 开始输入时，映射被关
闭直到输入 <code class="keystroke">CTRL-^</code> 为止。而插入模式和模式搜索却会分别记住上次使用的状态。需要输
入一个字符作为参数的命令，如 "f" 或 "t" 之类，也使用插入模式的状态。
   语言映射永远不能应用于已经映射的字符上。它们仅用于键入的字符上。这意味着输
入映射时，语言映射已经完成。


1.4 列 出 映 射                                         <b class="vimtag"> <a name="map-listing">map-listing</a> </b>

当列出映射时，前面两栏的字符表示 (可有多个):

<code class="section">      字 符     模 式   </code>
     <code class="special">&lt;Space&gt;</code>    普通、可视、选择和操作符等待
        n       普通
        v       可视和选择
        s       选择
        x       可视
        o       操作符等待
        !       插入和命令行
        i       插入
        l       插入、命令行和 Lang-Arg 模式的 ":lmap" 映射
        c       命令行
        t       终端作业

<code class="special">{rhs}</code> 之前可能显示一个特殊字符:
        *       表示它不可重映射
        &amp;       表示仅脚本的局部映射可以被重映射
        @       表示缓冲区的局部映射

从 <code class="special">{lhs}</code> 以后的第一个非空字符到行的末尾 (或 '|') 都被认为是 <code class="special">{rhs}</code> 的一部分。这
允许 <code class="special">{rhs}</code> 以一个空格结尾。

<code class="note">注意</code>: 在可视模式里使用映射时，你可以使用 "'&lt;" 位置标记，它表示当前缓冲区中最后
被选中的可视区域的开始  <a href="motion.html#'%3C">'&lt;</a> 。

 <a href="various.html#:filter">:filter</a>  命令可用于选择列出哪种映射。模式匹配 <code class="special">{lhs}</code> 和 <code class="special">{rhs}</code> 原始文本。

映射列出的同时不能新增或清除映射，如在定时器回调中。  <b class="vimtag"> <a name="E1309">E1309</a> </b>

                                                        <b class="vimtag"> <a name=":map-verbose">:map-verbose</a> </b>
如果 <a href="options.html#'verbose'">'verbose'</a> 非零，列出键映射的同时可以显示它在哪里定义。例如: 
<code class="example"></code>
<code class="example">        :verbose map &lt;C-W&gt;*</code>
<code class="example">        n  &lt;C-W&gt;*      * &lt;C-W&gt;&lt;C-S&gt;*</code>
<code class="example">                Last set from /home/abcd/.vimrc</code>
<code class="example"></code>
 <a href="various.html#:verbose-cmd">:verbose-cmd</a>  说明详情。


1.5 映 射 特 殊 键                                      <b class="vimtag"> <a name=":map-special-keys">:map-special-keys</a> </b>

有三种方法来映射一个特殊键:
1. Vi 兼容的方法: 对键码进行映射。通常这是一个以 <code class="special">&lt;Esc&gt;</code> 开头的序列。要输入一个
   这样的映射先输入 ":map " 然后再敲入功能键之前得先输入一个 <code class="keystroke">CTRL-V</code>。<code class="note">注意</code>如果
   键码在 termcap (t_ 开头的选项) 里，它会被自动转换到内码并变成映射的第二种方
   法 (除非 <a href="options.html#'cpoptions'">'cpoptions'</a> 里包括了 'k' 标志位)。
2. 第二种方法是使用功能键的内码。要输入这样的映射输入 <code class="keystroke">CTRL-K</code> 并敲要映射的功能
   键，或者使用 "#1"、"#2"、.. "#9"、"#0"、"<code class="special">&lt;Up&gt;</code>"、"<code class="special">&lt;S-Down&gt;</code>"、"<code class="special">&lt;S-F7&gt;</code>" 等等的
   形式 (参考键表  <a href="intro.html#key-notation">key-notation</a> ，所有从 <code class="special">&lt;Up&gt;</code> 开始的键都可以使用)。头十个功能
   键能以两种方式被定义: 仅用数字，比如 "#2"；或者使用 "<code class="special">&lt;F&gt;</code>"，如 "<code class="special">&lt;F2&gt;</code>"。两种
   都代表功能键 F2。"#0" 表示功能键 F10，由选项 't_f10' 定义，它在某些键盘上可
   能是 F0。<code class="special">&lt;&gt;</code> 的形式在 <a href="options.html#'cpoptions'">'cpoptions'</a> 包含 '&lt;' 标志位时不能使用。
3. 使用 termcap 条目，以 <code class="special">&lt;t_xx&gt;</code> 的形式出现，这里 "xx" 是 termcap 条目的名字。
   可以使用任何字符串条目。例如: 
<code class="example">     :map &lt;t_F3&gt; G</code>
   把功能键 13 映射成 "G"。<a href="options.html#'cpoptions'">'cpoptions'</a> 包括 '&lt;' 标志位时不能使用这种方式。

第二种和第三种方法的优点是不加修改就可以在不同的终端上使用 (功能键会被转换成相
同的内码或实际的键码，不论使用何种终端都是如此。termcap 必须正确才能正常工作，
并且必须使用相同的映射)。

细 节: Vim 首先检查是否从键盘输入的序列是否已被映射。否的话将试图使用终端键码
(参考  <a href="term.html#terminal-options">terminal-options</a> )。如果找到终端编码，它会被替换成内码。然后再次检查一
个映射是否已完成 (因此你也能把一个内码映射成其它东西)。在脚本文件中写入什么东
西取决于何者被识别。如果终端键码被识别为映射，写入键码本身；如果它被识别为一个
终端编码，则在脚本中写入内码。


1.6 特 殊 字 符                                         <b class="vimtag"> <a name=":map-special-chars">:map-special-chars</a> </b>
                                                <b class="vimtag"> <a name="map_backslash">map_backslash</a> </b> <b class="vimtag"> <a name="map-backslash">map-backslash</a> </b>
<code class="note">注意</code>这里仅提及 <code class="keystroke">CTRL-V</code> 可以作为用于映射和缩写的特殊字符。当 <a href="options.html#'cpoptions'">'cpoptions'</a> 不包含
'B' 时，反斜杠也可起到 <code class="keystroke">CTRL-V</code> 一样的作用，这时可以完全地使用 <code class="special">&lt;&gt;</code> 记法  <a href="intro.html#%3C%3E">&lt;&gt;</a> 。但
你不能期望 "<code class="special">&lt;C-V&gt;</code>" 像 <code class="keystroke">CTRL-V</code> 那样转换后来者的特殊含义。

要映射反斜杠，或者在 <code class="special">{rhs}</code> 中使用按本义出现的反斜杠，可以使用特殊字符序列
"<code class="special">&lt;Bslash&gt;</code>" 。这可以避免在使用嵌套映射时使用双反斜杠的需要。

                                                <b class="vimtag"> <a name="map_CTRL-C">map_CTRL-C</a> </b> <b class="vimtag"> <a name="map-CTRL-C">map-CTRL-C</a> </b>
<code class="special">{lhs}</code> 里可以使用 <code class="keystroke">CTRL-C</code>，但只有在 Vim 等待输入键时才可以，Vim 忙着做别的事情的
时候不行。如果 Vim 在忙，<code class="keystroke">CTRL-C</code> 总是中断/打断该命令。
使用 MS-Windows 上的 GUI 版本时 <code class="keystroke">CTRL-C</code> 能被映射以允许复制到剪贴板的命令。使用
<code class="keystroke">CTRL-Break</code> 来中断 Vim。

                                        <b class="vimtag"> <a name="map_space_in_lhs">map_space_in_lhs</a> </b> <b class="vimtag"> <a name="map-space_in_lhs">map-space_in_lhs</a> </b>
要在 <code class="special">{lhs}</code> 中包含一个空格，在前面输入一个 <code class="keystroke">CTRL-V</code> (每个空格之前实际要输入两个
<code class="keystroke">CTRL-V</code>)。
                                        <b class="vimtag"> <a name="map_space_in_rhs">map_space_in_rhs</a> </b> <b class="vimtag"> <a name="map-space_in_rhs">map-space_in_rhs</a> </b>
如果你需要 <code class="special">{rhs}</code> 以空格开头，使用 "<code class="special">&lt;Space&gt;</code>"。要与 Vi 完全兼容 (但不可读)，不要
使用  <a href="intro.html#%3C%3E">&lt;&gt;</a>  记法，在 <code class="special">{rhs}</code> 前面先输入一个单独的 <code class="keystroke">CTRL-V</code> (你必须输入 <code class="keystroke">CTRL-V</code> 两
次)。
                                                <b class="vimtag"> <a name="map_empty_rhs">map_empty_rhs</a> </b> <b class="vimtag"> <a name="map-empty-rhs">map-empty-rhs</a> </b>
你可以通过在一个单独的 <code class="keystroke">CTRL-V</code> (你必须输入 <code class="keystroke">CTRL-V</code> 两次) 后面什么也不输入来建立
一个空的 <code class="special">{rhs}</code>。不幸的是在 vimrc 文件中你不能使用这种方式。

                                                        <b class="vimtag"> <a name="%3CNop%3E">&lt;Nop&gt;</a> </b>
得到什么都不做的映射的更容易的方法是在 <code class="special">{rhs}</code> 中使用 "<code class="special">&lt;Nop&gt;</code>"。仅当  <a href="intro.html#%3C%3E">&lt;&gt;</a>  记法允
许时这种方法才生效。例如确保功能键 F8 什么事情都不做:
        :map  <code class="special">&lt;F8&gt;</code>  <code class="special">&lt;Nop&gt;</code>
        :map! <code class="special">&lt;F8&gt;</code>  <code class="special">&lt;Nop&gt;</code>

                                                        <b class="vimtag"> <a name="map-multibyte">map-multibyte</a> </b>
可以对多字节字符映射，但只能是整个字符。不能仅映射第一个字节。这是为了避免下面
场景中的问题:
        :set encoding=latin1
        :imap <code class="special">&lt;M-C&gt;</code> foo
        :set encoding=utf-8
<code class="special">&lt;M-C&gt;</code> 的映射是在 latin1 编码中被定义的，结果是一个 0xc3 字节。如果你在 UTF-8
解码中输入 á (0xe1 <code class="special">&lt;M-a&gt;</code>) 它是双字节 0xc3 0xa1。这个时候你不希望 0xc3 字节被映
射，否则的话将不能输入 á 字符了。

                                        <b class="vimtag"> <a name="%3CLeader%3E">&lt;Leader&gt;</a> </b> <b class="vimtag"> <a name="mapleader">mapleader</a> </b>
要定义一个使用 "g:mapleader" 变量的映射，可以使用特殊字串 "<code class="special">&lt;Leader&gt;</code>"。它会被
"g:mapleader" 的字串值所替换。如果 "g:mapleader" 未设置或为空，则用反斜杠代
替，例如:
        map <code class="special">&lt;Leader&gt;</code>A  oanother line<code class="special">&lt;Esc&gt;</code>
和下面一样: 
<code class="example">        map \A  oanother line&lt;Esc&gt;</code>
但是当 (老式脚本): 
<code class="example">        let mapleader = ","</code>
或 (Vim9 脚本): 
<code class="example">        g:mapleader = ","</code>
时，又相当于: 
<code class="example">        map ,A  oanother line&lt;Esc&gt;</code>
<code class="example"></code>
<code class="note">注意</code> "g:mapleader" 的值仅当映射在定义的时候被使用。之后就算 "g:mapleader" 被改
变，也不会影响已定义的映射。

                                        <b class="vimtag"> <a name="%3CLocalLeader%3E">&lt;LocalLeader&gt;</a> </b> <b class="vimtag"> <a name="maplocalleader">maplocalleader</a> </b>
<code class="special">&lt;LocalLeader&gt;</code> 和 <code class="special">&lt;Leader&gt;</code> 类似，除了它使用 "maplocalleader" 而非 "mapleader"
以外。<code class="special">&lt;LocalLeader&gt;</code> 用于局部于缓冲区的映射，例如: 
<code class="example">      :map &lt;buffer&gt; &lt;LocalLeader&gt;A  oanother line&lt;Esc&gt;</code>

在一个全局插件里应该使用 <code class="special">&lt;Leader&gt;</code> 而在一个文件类型插件里应该用 <code class="special">&lt;LocalLeader&gt;</code>。
"mapleader" 和 "maplocalleader" 可以是相同的。尽管如此，如果你把它们设为不同，
全局插件和文件类型插件的映射冲突的机会是不是会小一点呢？例如，你可以保持把
"mapleader" 设置为缺省的反斜杠，而设置 "maplocalleader" 为下划线。

                                                        <b class="vimtag"> <a name="map-%3CSID%3E">map-&lt;SID&gt;</a> </b>
在一个脚本中有一个特殊关键字叫 "<code class="special">&lt;SID&gt;</code>" 能被用来定义一个局部于脚本中的映射。
具体细节请参考  <a href="map.html#%3CSID%3E">&lt;SID&gt;</a> 。

                                                        <b class="vimtag"> <a name="%3CPlug%3E">&lt;Plug&gt;</a> </b>
叫做 "<code class="special">&lt;Plug&gt;</code>" 的特殊关键字可以用于一个内部映射，它不与任何键的序列匹配。这在插
件中有用  <a href="usr_51.html#using-%3CPlug%3E">using-&lt;Plug&gt;</a> 。

                                                        <b class="vimtag"> <a name="%3CMouseMove%3E">&lt;MouseMove&gt;</a> </b>
叫做 "<code class="special">&lt;MouseMove&gt;</code>" 的特殊关键字可用于处理鼠标移动。它必须用 <a href="options.html#'mousemoveevent'">'mousemoveevent'</a>
激活。目前只能用于 GUI 模式。 <a href="builtin.html#getmousepos()">getmousepos()</a>  函数可用于获取鼠标位置。

                                                        <b class="vimtag"> <a name="%3CChar%3E">&lt;Char&gt;</a> </b> <b class="vimtag"> <a name="%3CChar-%3E">&lt;Char-&gt;</a> </b>
要根据一个字符的十进制，八进制或十六进制数字形式进行映射，可以使用 <code class="special">&lt;Char&gt;</code> 来构
造:
        <code class="special">&lt;Char-123&gt;</code>      字符 123
        <code class="special">&lt;Char-033&gt;</code>      字符 27
        <code class="special">&lt;Char-0x7f&gt;</code>     字符 127
        <code class="special">&lt;S-Char-114&gt;</code>    字符 114 ('r') 加上 Shift ('R')
它可以用来在一个 <a href="options.html#'keymap'">'keymap'</a> 文件里指定一个 (多字节) 字符。大小写的区别此处不计。

                                                        <b class="vimtag"> <a name="map-comments">map-comments</a> </b>
在这些命令的后面不可能放置注释，因为 '"' 字符被认为是 <code class="special">{lhs}</code> 或 <code class="special">{rhs}</code> 的一部
分。不过，你可以用 |"，它开启了带注释的新空白命令。

                                                        <b class="vimtag"> <a name="map_bar">map_bar</a> </b> <b class="vimtag"> <a name="map-bar">map-bar</a> </b>
因为字符 '|' 用来分隔映射命令和后面的命令，所以包括 '|' 的 <code class="special">{rhs}</code> 要做一些特殊
的处理，有三种方法:
<code class="section">   使用      可用于                        示例 </code>
   <code class="special">&lt;Bar&gt;</code>     '&lt;' 不在 <a href="options.html#'cpoptions'">'cpoptions'</a> 里       :map _l :!ls <code class="special">&lt;Bar&gt;</code> more^M
   \|        'b' 不在 <a href="options.html#'cpoptions'">'cpoptions'</a> 里       :map _l :!ls \| more^M
   ^V|       总可以，Vim 和 Vi 都行        :map _l :!ls ^V| more^M

(这里 ^V 表示 <code class="keystroke">CTRL-V</code>；要输入一个 <code class="keystroke">CTRL-V</code> 你必须按键两次；在这里不能使用 <code class="special">&lt;&gt;</code> 记法
"<code class="special">&lt;C-V&gt;</code>")。

当你使用 <a href="options.html#'cpoptions'">'cpoptions'</a> 的缺省设置时三种方式都可以正常工作。

当 'b' 出现在 <a href="options.html#'cpoptions'">'cpoptions'</a> 中时，"\|" 会被认为是一个映射的结束，后面的是另一个
命令。这是为了和 Vi 兼容，但是和其它命令比较时有点不合常理。

                                                <b class="vimtag"> <a name="map_return">map_return</a> </b> <b class="vimtag"> <a name="map-return">map-return</a> </b>
当你的映射包含 Ex 命令时，你需要在其后放置行终结符才能让它执行。在这里推荐使用
<code class="special">&lt;CR&gt;</code>  (参考  <a href="intro.html#%3C%3E">&lt;&gt;</a> )。例如: 
<code class="example">   :map  _ls  :!ls -l %:S&lt;CR&gt;:echo "the end"&lt;CR&gt;</code>
<code class="example"></code>
在插入或命令行模式中输入时要避免字符被映射，可以先输入一个 <code class="keystroke">CTRL-V</code>。在插入模式
中如果 <a href="options.html#'paste'">'paste'</a> 选项被打开的话，映射也会被禁止。

                                                        <b class="vimtag"> <a name="map-error">map-error</a> </b>
<code class="note">注意</code> 当遇到错误时 (会导致一个错误信息，也可能会蜂鸣) 剩下的映射将不会被执行。
这是为了保持和 Vi 兼容。

<code class="note">注意</code> @zZtTfF[]rm'`"v 和 <code class="keystroke">CTRL-X</code> 命令的第二个字符 (参数) 不被映射。这样做是为了
能够使用所有的命名寄存器和位置标记，即使同名的命令被映射时也是如此。


1.7 映 射 哪 些 键                                      <b class="vimtag"> <a name="map-which-keys">map-which-keys</a> </b>

如果你要做一些映射，你得选择在 <code class="special">{lhs}</code> 中要用哪些键。你应该避免使用 Vim 命令所使
用的那些键。否则你将不能再使用这些命令了。下面是一些建议:
- 功能键 <code class="special">&lt;F2&gt;</code>、<code class="special">&lt;F3&gt;</code> 等；Shift 加功能键 <code class="special">&lt;S-F1&gt;</code>、<code class="special">&lt;S-F2&gt;</code> 等等。<code class="note">注意</code> <code class="special">&lt;F1&gt;</code> 已经用作
  帮助命令。
- 带 Alt 或 Meta 的键。取决于你的键盘，也可以用带重音的字符。 <a href="map.html#:map-alt-keys">:map-alt-keys</a> 
- 使用 '_' 或 ',' 字符然后加上任何其它的字符。"_" 和 "," 命令在 Vim 中是存在
  的 (参考  <a href="motion.html#_">_</a>  和  <a href="motion.html#,">,</a> )，但你也许永远不会用到它们。
- 使用和其它命令的同义的热键。例如: <code class="keystroke">CTRL-P</code> 和 <code class="keystroke">CTRL-N</code>。使用一个附加的字符可以定
  义更多的映射。
- <code class="special">&lt;Leader&gt;</code> 定义的键加上一到多个其它键。尤其对脚本有用。 <a href="map.html#mapleader">mapleader</a> 

参考文件 "index" 可以知道哪些键没有被使用，从而使映射不会覆盖任何内建的功能。
也可使用 ":help <code class="special">{key}</code>^D" 来找出是否一个键已经用于某些命令。(<code class="special">{key}</code> 用于指定你要
寻找的键，^D 是 <code class="keystroke">CTRL-D</code>)。


1.8 示 例                                               <b class="vimtag"> <a name="map-examples">map-examples</a> </b>

以下是一些例子 (照字面输入，如 "<code class="special">&lt;CR&gt;</code>" 需要输入四个字符；为此 <a href="options.html#'cpoptions'">'cpoptions'</a> 中不
应出现 '&lt;' 标志位)。 
<code class="example"></code>
<code class="example">   :map &lt;F3&gt;  o#include</code>
<code class="example">   :map &lt;M-g&gt; /foo&lt;CR&gt;cwbar&lt;Esc&gt;</code>
<code class="example">   :map _x    d/END/e&lt;CR&gt;</code>
<code class="example">   :map! qq   quadrillion questions</code>
<code class="example"></code>
计数相乘

如果你在激活映射前输入计数，实际效果就像是该计数在 <code class="special">{lhs}</code> (<code class="vim">译者注</code>: 疑为 <code class="special">{rhs}</code>)
之前输入一样。例如，对下面的映射: 
<code class="example">   :map &lt;F4&gt;  3w</code>
输入 2<code class="special">&lt;F4&gt;</code> 会得到 "23w"。不是移动 2 * 3 个单词，而是 23 个单词。
如果你希望得到计数相乘的效果，可使用表达式寄存器: 
<code class="example">   :map &lt;F4&gt;  @='3w'&lt;CR&gt;</code>
引号之间的部分是待执行的表达式。 <a href="change.html#@%20">@=</a> 


1.9 使 用 映 射                                         <b class="vimtag"> <a name="map-typing">map-typing</a> </b>

当你输入一个被映射序列的头部时 Vim 开始比较你的输入。如果匹配尚不完全，它会等
待更多的字符输入直到可以确定是否匹配。例如: 如果你映射了 map! "qq"，然后你输入
的第一个 'q' 将不会显示在屏幕上，直到你输入另一个 'q' 或其它字符。如果打开了
<a href="options.html#'timeout'">'timeout'</a> 选项 (这是缺省选项) Vim 仅会等待一秒钟 (或任何 <a href="options.html#'timeoutlen'">'timeoutlen'</a> 指定的时
间)。之后，它假定 'q' 已经不会再被输入。如果你的输入很慢，或者你的系统很慢，复
位 <a href="options.html#'timeout'">'timeout'</a> 选项。这时，你可能还需要是否置位 <a href="options.html#'ttimeout'">'ttimeout'</a> 选项。

                                                        <b class="vimtag"> <a name="map-precedence">map-precedence</a> </b>
缓冲区局部映射 ( <a href="map.html#:map-%3Cbuffer%3E">:map-&lt;buffer&gt;</a>  所定义的) 优先于全局映射。如果缓冲区局部映射和
全局映射完全相同，Vim 使用缓冲区局部映射。另外如果映射以 <code class="special">&lt;nowait&gt;</code> 定义的话，
Vim 立即使用完整出现的映射，即便有一个更长的映射使用相同的前缀。例如，给定以下
的映射: 
<code class="example">    :map &lt;buffer&gt; &lt;nowait&gt; \a   :echo "Local \a"&lt;CR&gt;</code>
<code class="example">    :map                   \abc :echo "Global \abc"&lt;CR&gt;</code>
键入 \a 后会立即使用那个缓冲区局部映射。Vim 不再等待更多的字符来判断用户是否想
输入 \abc。

                                                        <b class="vimtag"> <a name="map-keys-fails">map-keys-fails</a> </b>
有若干情况键码可能不被识别:
- Vim 仅能读取部分的键码。通常仅仅是第一个字符。在某些 Unix 版本的 xterm 上有
  这种情况。
- 键码在已经映射的字符之后。举例来说，"<code class="special">&lt;F1&gt;</code><code class="special">&lt;F1&gt;</code>" 或 "g<code class="special">&lt;F1&gt;</code>"。

其结果是在这种情况下键码不会被识别，所以映射失败。有两种方法可以避免此问题:

- 从 <a href="options.html#'cpoptions'">'cpoptions'</a> 中删除 'K' 标志位。这会使 Vim 等待功能键的其余部分。
- 使用 <code class="special">&lt;F1&gt;</code> 到 <code class="special">&lt;F4&gt;</code> 时，实际产生的键码可能是 <code class="special">&lt;xF1&gt;</code> 到 <code class="special">&lt;xF4&gt;</code>。存在 <code class="special">&lt;xF1&gt;</code> 到
  <code class="special">&lt;F1&gt;</code>，<code class="special">&lt;xF2&gt;</code> 到 <code class="special">&lt;F2&gt;</code> 的映射等，但是在映射的后一半的那些依然不会被识别。确认从
  <code class="special">&lt;F1&gt;</code> 到 <code class="special">&lt;F4&gt;</code> 的键码是正确的: 
<code class="example">        :set &lt;F1&gt;=&lt;type CTRL-V&gt;&lt;type F1&gt;</code>
  以四个字符输入 <code class="special">&lt;F1&gt;</code>。"=" 号后面的部分必须输入实际的字符而不是字面的文本。
另一种解决方法是在映射中为第二个特殊键使用实际的键码: 
<code class="example">        :map &lt;F1&gt;&lt;Esc&gt;OP :echo "yes"&lt;CR&gt;</code>
不要输入一个真正的 <code class="special">&lt;Esc&gt;</code>，总之 Vim 将识别键码并把它替换为 <code class="special">&lt;F1&gt;</code>。

另一个问题可能是保持 ALT 或 Meta 的时候，终端在前面附加 ESC 而不是给第 8 位置
位。见  <a href="map.html#:map-alt-keys">:map-alt-keys</a> 。

                                                <b class="vimtag"> <a name="recursive_mapping">recursive_mapping</a> </b>
如果 <code class="special">{rhs}</code> 中包括了 <code class="special">{lhs}</code>，那么你定义了一个递归映射。当 <code class="special">{lhs}</code> 被输入，它会被替
换成 <code class="special">{rhs}</code>。当遇到 <code class="special">{rhs}</code> 中包含的 <code class="special">{lhs}</code> 又会被替换成 <code class="special">{rhs}</code>，依此类推。
这可用来使一个命令重复无数次。这种情况唯一的问题是出错是停止它的唯一方法。解决
迷宫的宏会用到这个，去那里找找例子吧。有一个例外: 如果 <code class="special">{rhs}</code> 以 <code class="special">{lhs}</code> 开始，第
一个字符不会被再次映射 (这与 Vi 兼容)。
例如: 
<code class="example">   :map ab abcd</code>
将执行 "a" 命令并且在文本中插入 "bcd"。<code class="special">{rhs}</code> 中的 "ab" 不会被再次映射。

如果你要交换两个键的含义，应该使用 :noremap 命令。例如: 
<code class="example">   :noremap k j</code>
<code class="example">   :noremap j k</code>
这会交换光标上移和光标下移命令。

如果使用普通 :map 命令，并且 <a href="options.html#'remap'">'remap'</a> 选项被打开，映射一直进行直到文本不再是某
个 <code class="special">{lhs}</code> 的一部分。例如，如果你用: 
<code class="example">   :map x y</code>
<code class="example">   :map y x</code>
Vim 将把 x 替换成 y，并把 y 替换成 x，等等。这种情况会发生 <a href="options.html#'maxmapdepth'">'maxmapdepth'</a> 次
(缺省为 1000)，然后 Vim 会给出错误信息 "recursive mapping" (递归映射)。

                                                        <b class="vimtag"> <a name=":map-undo">:map-undo</a> </b>
如果你在一个被映射的序列中包含了一个 undo 命令，将会把文本带回宏执行前的状态。
这和原始的 Vi 是兼容的，只要被映射的序列仅包含一个 undo 命令 (原始的 Vi 中被映
射的序列有两个 undo 命令是无意义的，你会得到第一个 undo 之前的文本)。


1.10 映 射 ALT 键                                       <b class="vimtag"> <a name=":map-alt-keys">:map-alt-keys</a> </b>

GUI 上，Vim 自己处理 Alt 键，所以用 ALT 键的映射应该总没有问题。但在终端上，
Vim 得到字节的序列，它必须自己判断是不是按了 ALT 键。

如果终端支持 modifyOtherKeys 模式且打开，Vim 可以识别更多的键组合，见下
 <a href="map.html#modifyOtherKeys">modifyOtherKeys</a> 。Kitty 键盘协议也类似，见  <a href="map.html#kitty-keyboard-protocol">kitty-keyboard-protocol</a> 。

Vim 缺省假设按下 ALT 键等于置位输入字符的第 8 位。多数正常的终端如此工作，包括
xterm、aterm 和 rxvt。假如你的 <code class="special">&lt;A-k&gt;</code> 映射不能工作，可能的原因是你的终端用在字
符前加上 ESC 前缀的方法。但是你本来也可能在字符前输入 ESC，这时 Vim 就不知道到
底发生了什么 (只能检查字符间的延迟，但这并不可靠)。

在此文写作时，有些主流的终端，如 gnome-terminal 和 konsole，使用 ESC 前缀。没
有办法让它们用置位第 8 位来代替。Xterm 缺省应该没有问题。Aterm 和 rxvt 启动时
如果使用 "--meta8" 参数也可以如此。你也可以修改资源来达到目的:
"metaSendsEscape"、"eightBitInput" 和 "eightBitOutput"。

Linux 控制台上，可以用 "setmetamode" 命令切换此行为。记住不使用 ESC 前缀可能和
其它程序发生冲突。确保你的 bash 把 "convert-meta" 选项设为 "on"，确保 Meta 键
盘绑定仍然工作 (这是缺省的 readline 行为，除非你的系统配置专门作了改变)。为
此，你需要加入这行: 
<code class="example"></code>
<code class="example">        set convert-meta on</code>
<code class="example"></code>
到你的 ~/.inputrc 文件。如果你新建此文件，可能想把: 
<code class="example"></code>
<code class="example">        $include /etc/inputrc</code>
<code class="example"></code>
放在第一行，如果此文件在你的系统中存在的话。这样可以保持全局的选项设置。不过，
这可能会使 umlaut 这样的特殊字符的输入有问题。这时，输入字符前用 <code class="keystroke">CTRL-V</code> 前导。

要知道有报告说 convert-meta 使得 UTF-8 locale 的使用有问题。在 xterm 这样的终
端里，可以在 "Main Options" 菜单里随时切换 "metaSendsEscape" 资源，或者终端上
按 Ctrl-LeftClick 也可以；如果你需要给 Vim 之外的其它应用程序发送 ESC，这是最
后应急的方法。


1.11 映 射 META 键                                      <b class="vimtag"> <a name=":map-meta-keys">:map-meta-keys</a> </b>

使用 Meta 修饰符的工作方式非常类似于 Alt 键。你的键盘上什么键生成 Meta 修饰符
取决于你的键盘和配置。

<code class="note">注意</code> <code class="special">&lt;M-a&gt;</code> 映射实际上使用 Alt 键。这很容易引起混淆！没法改变，否则就不能后向兼
容。

Meta 修饰符使用 "T" 字符。例如，要在插入模式中映射 Meta-b: 
<code class="example">        :imap &lt;T-b&gt; terrible</code>
<code class="example"></code>
<code class="example"></code>
1.12 modifyOtherKeys 模 式 映 射                        <b class="vimtag"> <a name="modifyOtherKeys">modifyOtherKeys</a> </b>

Xterm 和一些其它的终端可以进入一种模式，其中带修饰符的键可以使用特殊的转义代码
发送。Vim 识别这些代码，所以可以区别 <code class="keystroke">CTRL-H</code> 和退格键，尽管退格键也发送字符 8。
还有许许多特殊键，如 Tab 和 <code class="keystroke">CTRL-I</code>，否则映射时就不能区别开。

xterm 在内建的 termcap 项目中打开了 modifyOtherKeys。如果没有用，可以在 vimrc
中打开 modifyOtherKeys: 
<code class="example">      let &amp;t_TI = "\&lt;Esc&gt;[&gt;4;2m"</code>
<code class="example">      let &amp;t_TE = "\&lt;Esc&gt;[&gt;4;m"</code>
<code class="example"></code>
这会设置 modifyOtherKeys 为 2 级。<code class="note">注意</code> modifyOtherKeys 1 级不可用。有的终端不
支持 2 级，它们发送的键码 Vim 无法正确识别。

万一 modifyOtherKeys 模式造成问题，可以关闭之: 
<code class="example">      let &amp;t_TI = ""</code>
<code class="example">      let &amp;t_TE = ""</code>
这不会立即生效。要避免重启 Vim 但要使之生效，执行外壳命令，如:  <code class="badlink">!ls</code>   或把它们
加入  <a href="starting.html#vimrc">vimrc</a> 。

modifyOtherKeys 打开时可以映射 &lt;C-[&gt; 和 &lt;C-S-{&gt;: 
<code class="example">        imap &lt;C-[&gt; [[[</code>
<code class="example">        imap &lt;C-S-{&gt; {{{</code>
如果没有 modifyOtherKeys，&lt;C-[&gt; 和 &lt;C-{&gt; 与 Esc 无法区分。<code class="note">注意</code>这里用 &lt;C-{&gt; 而
不是 &lt;C-S-[&gt; 或 &lt;C-S-{&gt;。这适用于绝大多数键盘。类似的，使用 &lt;C-}&gt; 而不是
&lt;C-S-]&gt; 或 &lt;C-S-}&gt;，使用 &lt;C-|&gt; 而不是 &lt;C-S-\&gt; 或 &lt;C-S-|&gt;。<code class="note">注意</code> '|' 在映射中有
特殊含义，见  <a href="map.html#map-bar">map-bar</a> 。

<code class="note">警告</code>: 如果映射了 &lt;C-[&gt;，有很大可能会破坏任何 Esc 开始的键码。要确保该映射出现
在其它映射 <code class="emphasis">之后</code> 。

从 xterm 版本 377 开始，Vim 可以发送检测 modifyOtherKeys 状态的请求。为此使用
<a href="term.html#'t_RK'">'t_RK'</a> termcap 项目。如果有响应，Vim 就知道是否打开了 2 级的 modifyOtherKeys，
并相应地处理映射。

版本 377 之前，Vim 如果看到确定是 modifyOtherKeys 创建的转义序列，会据此自动检
测是否打开了 modifyOtherKeys。要确认 Vim 是否检测到了这样的转义序列，可用
`:verbose map`，此时首行显示 "Seen modifyOtherKeys: true" (可能经过翻译)。

此自动检测机制取决于接收到 "<code class="special">&lt;1b&gt;</code>[27;" 开始的转义码，这是 xterm 发送这些键码的
通常方式。不过如果用了 <b class="vimtag"> <a name="formatOtherKeys">formatOtherKeys</a> </b> 资源，会使用另一种 Vim 不能识别的形
式，所以千万不要设置 formatOtherKeys。

已知的一个副作用是在插入模式中在 <code class="keystroke">CTRL-V</code> 键后插入的是原始转义序列。这可用来检查
是否打开了 modifyOtherKeys。插入模式下按 <code class="keystroke">CTRL-SHIFT</code>-V <code class="keystroke">CTRL-V</code>，如果得到一个字节
那么 modifyOtherKeys 是关闭的，如果得到 <code class="special">&lt;1b&gt;</code>[27;5;118~，那么它已打开。

<code class="note">注意</code> xterm 376 及之前版本有个漏洞，会把 Shift-Esc 作为普通 Esc 代码发送，丢掉
了 Shift 修饰符。

<a href="options.html#'esckeys'">'esckeys'</a> 选项如果关闭，在插入模式会屏蔽 modifyOtherKeys，以免每个带修饰符的键
都会退出插入模式。


1.13 使用 Kitty 键盘协议的映射                   <b class="vimtag"> <a name="kitty-keyboard-protocol">kitty-keyboard-protocol</a> </b>

<a href="options.html#'term'">'term'</a> 值包含 "kitty" 时，Vim 会发送转义序列以打开 Kitty 键盘协议。可用
<a href="options.html#'keyprotocol'">'keyprotocol'</a> 选项改变此行为。

和 modifyOtherKeys 一样，这可用来区别更多的带修饰符的键。另外，此协议为 Esc 键
发送转义序列，这样 Vim 就无须用超时来判断接收到的 Esc 字符是按了 Esc 键还是转
义序列的开始。

Vim 如果看到状态请求 (应是  <a href="term.html#t_TI">t_TI</a>  termcap 项目的一部分) 的响应，会自动检测
Kitty 键盘协议是否打开。要确认 Vim 是否检测到了这样的转义序列，可用: 
<code class="example">        :verbose map</code>
此时首行显示 "Kitty keyboard protocol: <code class="special">{value}</code>" (可能经过翻译)。<code class="special">{value}</code> 的含义
是:
        Unknown         尚未收到状态
        Off             不使用协议
        On              正在使用协议
        Disabled        曾经使用过协议但被 <a href="term.html#'t_TE'">'t_TE'</a> 关闭
        Cleared         被 <a href="term.html#'t_TE'">'t_TE'</a> 关闭，之前状态未知


1.14 映 射 操 作 符                                     <b class="vimtag"> <a name=":map-operator">:map-operator</a> </b>

操作符应用于 <code class="special">{motion}</code> 命令之前。要定义你自己的操作符，你需要先创建映射来设置
<a href="options.html#'operatorfunc'">'operatorfunc'</a> 选项，然后调用  <a href="map.html#g@">g@</a>  操作符。这样用户输入 <code class="special">{motion}</code> 命令后，会调
用指定的函数。

                                                        <b class="vimtag"> <a name="g@">g@</a> </b> <b class="vimtag"> <a name="E774">E774</a> </b> <b class="vimtag"> <a name="E775">E775</a> </b>
g@<code class="special">{motion}</code>              调用 <a href="options.html#'operatorfunc'">'operatorfunc'</a> 选项设置的函数。
                        '[ 位置标记定位在 <code class="special">{motion}</code> 跨越的文本的开始处，而 ']
                        位置标记在此文本的结束处。
                        函数调用时，带一个字符串参数:
                              参数               如果
                            "line"      <code class="special">{motion}</code> 本是  <a href="motion.html#linewise">linewise</a> 
                            "char"      <code class="special">{motion}</code> 本是  <a href="motion.html#characterwise">characterwise</a> 
                            "block"     <code class="special">{motion}</code> 本是  <a href="visual.html#blockwise-visual">blockwise-visual</a> 
                        此类型可以强制，见  <code class="badlink">force-motion</code> 。
                        <code class="notvi">{仅当编译时加入  <a href="various.html#+eval">+eval</a>  特性才有效}</code>

这里是一例，<code class="special">&lt;F4&gt;</code> 来计算空格数目: 
<code class="example"></code>
<code class="example">        nnoremap &lt;expr&gt; &lt;F4&gt; CountSpaces()</code>
<code class="example">        xnoremap &lt;expr&gt; &lt;F4&gt; CountSpaces()</code>
<code class="example">        " 在一行上按两次 &lt;F4&gt; 也可以</code>
<code class="example">        nnoremap &lt;expr&gt; &lt;F4&gt;&lt;F4&gt; CountSpaces() .. '_'</code>
<code class="example"></code>
<code class="example">        function CountSpaces(context = {}, type = '') abort</code>
<code class="example">          if a:type == ''</code>
<code class="example">            let context = #{</code>
<code class="example">              \ dot_command: v:false,</code>
<code class="example">              \ extend_block: '',</code>
<code class="example">              \ virtualedit: [&amp;l:virtualedit, &amp;g:virtualedit],</code>
<code class="example">              \ }</code>
<code class="example">            let &amp;operatorfunc = function('CountSpaces', [context])</code>
<code class="example">            set virtualedit=block</code>
<code class="example">            return 'g@'</code>
<code class="example">          endif</code>
<code class="example"></code>
<code class="example">          let save = #{</code>
<code class="example">            \ clipboard: &amp;clipboard,</code>
<code class="example">            \ selection: &amp;selection,</code>
<code class="example">            \ virtualedit: [&amp;l:virtualedit, &amp;g:virtualedit],</code>
<code class="example">            \ register: getreginfo('"'),</code>
<code class="example">            \ visual_marks: [getpos("'&lt;"), getpos("'&gt;")],</code>
<code class="example">            \ }</code>
<code class="example"></code>
<code class="example">          try</code>
<code class="example">            set clipboard= selection=inclusive virtualedit=</code>
<code class="example">            let commands = #{</code>
<code class="example">              \ line: "'[V']",</code>
<code class="example">              \ char: "`[v`]",</code>
<code class="example">              \ block: "`[\&lt;C-V&gt;`]",</code>
<code class="example">              \ }[a:type]</code>
<code class="example">            let [_, _, col, off] = getpos("']")</code>
<code class="example">            if off != 0</code>
<code class="example">              let vcol = getline("'[")-&gt;strpart(0, col + off)-&gt;strdisplaywidth()</code>
<code class="example">              if vcol &gt;= [line("'["), '$']-&gt;virtcol() - 1</code>
<code class="example">                let a:context.extend_block = '$'</code>
<code class="example">              else</code>
<code class="example">                let a:context.extend_block = vcol .. '|'</code>
<code class="example">              endif</code>
<code class="example">            endif</code>
<code class="example">            if a:context.extend_block != ''</code>
<code class="example">              let commands ..= 'oO' .. a:context.extend_block</code>
<code class="example">            endif</code>
<code class="example">            let commands ..= 'y'</code>
<code class="example">            execute 'silent noautocmd keepjumps normal! ' .. commands</code>
<code class="example">            echomsg getreg('"')-&gt;count(' ')</code>
<code class="example">          finally</code>
<code class="example">            call setreg('"', save.register)</code>
<code class="example">            call setpos("'&lt;", save.visual_marks[0])</code>
<code class="example">            call setpos("'&gt;", save.visual_marks[1])</code>
<code class="example">            let &amp;clipboard = save.clipboard</code>
<code class="example">            let &amp;selection = save.selection</code>
<code class="example">            let [&amp;l:virtualedit, &amp;g:virtualedit] = get(a:context.dot_command ? save : a:context, 'virtualedit')</code>
<code class="example">            let a:context.dot_command = v:true</code>
<code class="example">          endtry</code>
<code class="example">        endfunction</code>
<code class="example"></code>
这里 <code class="special">&lt;expr&gt;</code> 映射的使用是为了可以获取任何前缀计数和寄存器。这可用于避免使用命令
行，后者会触发 CmdlineEnter 和 CmdlineLeave 自动命令。

<code class="note">注意</code> <a href="options.html#'selection'">'selection'</a> 选项暂时设为 "inclusive"，以便可视模式下用 '[ 到 '] 位置标记
可以抽出正确的文本。

也要 <code class="note">注意</code> <a href="options.html#'clipboard'">'clipboard'</a> 选项值如果包含  <code class="badlink">unnamed</code>  或  <code class="badlink">unnamedplus</code>  的话，会临时清
空，以避免覆盖  <code class="badlink">"*</code>  或  <code class="badlink">"+</code>  寄存器。

 <a href="builtin.html#mode()">mode()</a>  函数会返回操作符应用之后的那个状态。

下例使用匿名函数以建立普通模式操作符，给当前行的文本加引号包围: 
<code class="example"></code>
<code class="example">        nnoremap &lt;F4&gt; &lt;Cmd&gt;let &amp;opfunc='{t -&gt;</code>
<code class="example">                                \ getline(".")</code>
<code class="example">                                \ -&gt;split("\\zs")</code>
<code class="example">                                \ -&gt;insert("\"", col("'']"))</code>
<code class="example">                                \ -&gt;insert("\"", col("''[") - 1)</code>
<code class="example">                                \ -&gt;join("")</code>
<code class="example">                                \ -&gt;setline(".")}'&lt;CR&gt;g@</code>
<code class="example"></code>
</section><hr class="doubleline" /><section class=inner>
<h4>2. 缩写                 <b class="vimtag"> <a name="abbreviations">abbreviations</a> </b> <b class="vimtag"> <a name="Abbreviations">Abbreviations</a> </b></h4>
缩写在插入，替换和命令行模式中使用。如果你输入一个是缩写的单词，它会被替换成所
表示的东西。这可以在经常输入的长单词时节省键击。并且能用它来自动更正经常犯的拼
写错误。例如:

        :iab ms Microsoft
        :iab tihs this

有三种类型的缩写:

full-id   "full-id" 类型完全由关键字字符组成 (字母和 <a href="options.html#'iskeyword'">'iskeyword'</a> 选项的字符)。
          这是最普通的缩写。

          例如: "foo"，"g3"，"-1"

end-id    "end-id" 类型以一个关键字字符结尾，但所有其它字符都不是关键字字符。

          例如: "#i"，"..f"，"$/7"

non-id    "non-id" 类型以一个非关键字字符结尾，其它字符可以是任意类型，除了空
          格和制表。<code class="notvi">{Vi 不支持这种类型}</code>

          例如: "def#"，"4/7$"

不能被缩写的字串例子: "a.b"，"#def"，"a b"，"_$r"

仅当你输入一个非关键字字符时缩写才会被识别，这也包括用 <code class="special">&lt;Esc&gt;</code> 退出插入模式或用
<code class="special">&lt;CR&gt;</code> 结束一个命令的情形。结束缩写的非关键字字符被插入到缩写的扩展后面。一个例
外是字符 &lt;C-]&gt;，它用来扩展一个缩写，但不插入任何附加字符。

例如: 
<code class="example">   :ab hh       hello</code>
            "hh<code class="special">&lt;Space&gt;</code>" 被扩展为 "hello<code class="special">&lt;Space&gt;</code>"
            "hh&lt;C-]&gt;" 被扩展为 "hello"

光标前的字符必需和缩写匹配。每种类型还有附加规则:

full-id   匹配的前面是一个非关键字字符，或者是在行或插入的开始。例外: 当缩写仅
          有一个字符时，如果它前面有一个非关键字字符则不会被识别，除非那是空格
          和制表。不过，命令行上忽略 "'&lt;,'&gt;" (或其它标记) 部分，就像命令行从那
          之后开始那样。

end-id    匹配的前面是一个关键字字符，或者空格或制表，或者行或插入的开始。

non-id    匹配的前面是一个空格、制表或者行或插入的开始。

例如: (<code class="special">{CURSOR}</code> 是你输入一个非关键字字符的地方) 
<code class="example">   :ab foo   four old otters</code>
                " foo<code class="special">{CURSOR}</code>"    被扩展为 " four old otters"
                " foobar<code class="special">{CURSOR}</code>" 不被扩展
                "barfoo<code class="special">{CURSOR}</code>"  不被扩展

<code class="example">   :ab #i #include</code>
                "#i<code class="special">{CURSOR}</code>"      被扩展为 "#include"
                "&gt;#i<code class="special">{CURSOR}</code>"     不被扩展

<code class="example">   :ab ;; &lt;endofline&gt;</code>
                "test;;"          不被扩展
                "test ;;"         被扩展为 "test <code class="special">&lt;endofline&gt;</code>"

要在插入模式中避免缩写: 在会启动缩写的的字符之前面输入 <code class="keystroke">CTRL-V</code>，例如 <code class="keystroke">CTRL-V</code>
<code class="special">&lt;Space&gt;</code>。或者先输入缩写的部分，以 <code class="special">&lt;Esc&gt;</code> 退出插入模式，再用 'a' 重新进入插入模
式并输入剩下的部分。

要在命令行模式中避免缩写: 在缩写的某处输入 <code class="keystroke">CTRL-V</code> 两次来避免它被替换。不然，一
个普通字符前面的 <code class="keystroke">CTRL-V</code> 通常会被忽略。

缩写进行之后移动光标是可能的: 
<code class="example">   :iab if if ()&lt;Left&gt;</code>
如果 <a href="options.html#'cpoptions'">'cpoptions'</a> 里面包含 '&lt;' 标志位时，这不能正常工作。 <a href="intro.html#%3C%3E">&lt;&gt;</a> 

你甚至可以做更复杂的事情。例如，要消灭一个缩写后面输入的空格: 
<code class="example">   func Eatchar(pat)</code>
<code class="example">      let c = nr2char(getchar(0))</code>
<code class="example">      return (c =~ a:pat) ? '' : c</code>
<code class="example">   endfunc</code>
<code class="example">   iabbr &lt;silent&gt; if if ()&lt;Left&gt;&lt;C-R&gt;=Eatchar('\s')&lt;CR&gt;</code>
<code class="example"></code>
没有缺省的缩写。

缩写永远不会递归。你可以设置 ":ab f f-o-o" 而不会有任何问题。但是缩写能被映
射。{一些版本的 Vi 支持递归缩写，这毫无道理}

<a href="options.html#'paste'">'paste'</a> 选项打开时，缩写被禁止。

                                <b class="vimtag"> <a name=":abbreviate-local">:abbreviate-local</a> </b> <b class="vimtag"> <a name=":abbreviate-%3Cbuffer%3E">:abbreviate-&lt;buffer&gt;</a> </b>
和映射一样，缩写可以被局部于一个缓冲区之内。这经常用于  <a href="usr_43.html#filetype-plugin">filetype-plugin</a>  文
件。一个 C 插件文件的例子: 
<code class="example">        :abb &lt;buffer&gt; FF  for (i = 0; i &lt; ; ++i)</code>

                                                <b class="vimtag"> <a name=":ab">:ab</a> </b> <b class="vimtag"> <a name=":abbreviate">:abbreviate</a> </b>
:ab[breviate]           列出所有的缩写。第一栏中的字符表示该缩写作用的模式:
                        'i' 指插入模式，'c' 指命令行模式，'!' 指两种模式都有。
                        这和映射的相同，参看  <a href="map.html#map-listing">map-listing</a>  。

                                                <b class="vimtag"> <a name=":abbreviate-verbose">:abbreviate-verbose</a> </b>
如果 <a href="options.html#'verbose'">'verbose'</a> 非零，缩写列出的同时显示它最近定义的位置。例如: 
<code class="example"></code>
<code class="example">        :verbose abbreviate</code>
<code class="example">        !  teh           the</code>
<code class="example">                Last set from /home/abcd/vim/abbr.vim</code>
<code class="example"></code>
 <a href="various.html#:verbose-cmd">:verbose-cmd</a>  说明详情。

:ab[breviate] <code class="special">{lhs}</code>     列出以 <code class="special">{lhs}</code> 开头的缩写

:ab[breviate] [<code class="special">&lt;expr&gt;</code>] [<code class="special">&lt;buffer&gt;</code>] <code class="special">{lhs}</code> <code class="special">{rhs}</code>
                        增加一个从 <code class="special">{lhs}</code> 到 <code class="special">{rhs}</code> 的缩写。如果 <code class="special">{lhs}</code> 已经存在
                        则它会被替换成新的 <code class="special">{rhs}</code>。<code class="special">{rhs}</code> 可包含空格。
                         <a href="map.html#:map-%3Cexpr%3E">:map-&lt;expr&gt;</a>  说明可选的 <code class="special">&lt;expr&gt;</code> 参数。
                         <a href="map.html#:map-%3Cbuffer%3E">:map-&lt;buffer&gt;</a>  说明可选的 <code class="special">&lt;buffer&gt;</code> 参数。

                                                <b class="vimtag"> <a name=":una">:una</a> </b> <b class="vimtag"> <a name=":unabbreviate">:unabbreviate</a> </b>
:una[bbreviate] [<code class="special">&lt;buffer&gt;</code>] <code class="special">{lhs}</code>
                        从列表中删除 <code class="special">{lhs}</code> 的缩写。如果找不到，删除 <code class="special">{rhs}</code> 匹配
                        这里的 <code class="special">{lhs}</code> 参数的缩写。这是为了方便你删除扩展后的缩
                        写。要避免扩展，插入 <code class="keystroke">CTRL-V</code> (记住输入两次)。

                                                <b class="vimtag"> <a name=":norea">:norea</a> </b> <b class="vimtag"> <a name=":noreabbrev">:noreabbrev</a> </b>
:norea[bbrev] [<code class="special">&lt;expr&gt;</code>] [<code class="special">&lt;buffer&gt;</code>] <code class="special">[lhs]</code> <code class="special">[rhs]</code>
                        与 ":ab" 一样，但 <code class="special">{rhs}</code> 不进行重映射。

                                                <b class="vimtag"> <a name=":ca">:ca</a> </b> <b class="vimtag"> <a name=":cab">:cab</a> </b> <b class="vimtag"> <a name=":cabbrev">:cabbrev</a> </b>
:ca[bbrev] [<code class="special">&lt;expr&gt;</code>] [<code class="special">&lt;buffer&gt;</code>] <code class="special">[lhs]</code> <code class="special">[rhs]</code>
                        与 ":ab" 一样，但仅在命令行模式中使用。

                                                <b class="vimtag"> <a name=":cuna">:cuna</a> </b> <b class="vimtag"> <a name=":cunabbrev">:cunabbrev</a> </b>
:cuna[bbrev] <code class="special">{lhs}</code>      与 ":una" 一样，但仅在命令行模式中使用。

                                                <b class="vimtag"> <a name=":cnorea">:cnorea</a> </b> <b class="vimtag"> <a name=":cnoreabbrev">:cnoreabbrev</a> </b>
:cnorea[bbrev] [<code class="special">&lt;expr&gt;</code>] [<code class="special">&lt;buffer&gt;</code>] <code class="special">[lhs]</code> <code class="special">[rhs]</code>
                        与 ":ab" 一样，但仅在命令行模式中使用并且 <code class="special">{rhs}</code> 不进行
                        重映射。

                                                <b class="vimtag"> <a name=":ia">:ia</a> </b> <b class="vimtag"> <a name=":iabbrev">:iabbrev</a> </b>
:ia[bbrev] [<code class="special">&lt;expr&gt;</code>] [<code class="special">&lt;buffer&gt;</code>] <code class="special">[lhs]</code> <code class="special">[rhs]</code>
                        与 ":ab" 一样，但仅在插入模式中使用。

                                                <b class="vimtag"> <a name=":iuna">:iuna</a> </b> <b class="vimtag"> <a name=":iunabbrev">:iunabbrev</a> </b>
:iuna[bbrev] <code class="special">{lhs}</code>      与 ":una" 一样，但仅在插入模式中使用。

                                                <b class="vimtag"> <a name=":inorea">:inorea</a> </b> <b class="vimtag"> <a name=":inoreabbrev">:inoreabbrev</a> </b>
:inorea[bbrev] [<code class="special">&lt;expr&gt;</code>] [<code class="special">&lt;buffer&gt;</code>] <code class="special">[lhs]</code> <code class="special">[rhs]</code>
                        与 ":ab" 一样，但仅在插入模式中使用并且 <code class="special">{rhs}</code> 不进行重
                        映射。

                                                        <b class="vimtag"> <a name=":abc">:abc</a> </b> <b class="vimtag"> <a name=":abclear">:abclear</a> </b>
:abc[lear] [<code class="special">&lt;buffer&gt;</code>]   删除所有的缩写。

                                                        <b class="vimtag"> <a name=":iabc">:iabc</a> </b> <b class="vimtag"> <a name=":iabclear">:iabclear</a> </b>
:iabc[lear] [<code class="special">&lt;buffer&gt;</code>]  为插入模式删除所有的缩写。

                                                        <b class="vimtag"> <a name=":cabc">:cabc</a> </b> <b class="vimtag"> <a name=":cabclear">:cabclear</a> </b>
:cabc[lear] [<code class="special">&lt;buffer&gt;</code>]  为命令行模式删除所有的缩写。

                                                        <b class="vimtag"> <a name="using_CTRL-V">using_CTRL-V</a> </b>
在一个缩写的 <code class="special">{rhs}</code> 中使用特殊字符是可能的。<code class="keystroke">CTRL-V</code> 可以用来避免多数不可显示字符
的特殊含义。需要输入多少个 <code class="keystroke">CTRL-V</code> 取决于你如何输入缩写。此处讨论同样适用于映
射。这里使用一个例子说明。

假设你需要把 "esc" 缩写为输入一个 <code class="special">&lt;Esc&gt;</code> 字符。当你在 Vim 中输入 ":ab" 命令，你
必需这样输入: (这里 ^V 是一个 <code class="keystroke">CTRL-V</code> 并且 ^[ is <code class="special">&lt;Esc&gt;</code>)

你输入:   ab esc ^V^V^V^V^V^[

        所有的键盘输入都经过 ^V 引用解释，所以第一个，第三个，和第五个 ^V 字符
        只是为了把第二个、第四个 ^V 和 ^[ 输入到命令行里。

你看到:    ab esc ^V^V^[

        命令行里在 ^[ 之前包含两个实际的 ^V。如果你采用这种方法，这是该行在你
        的 .exrc 文件应该出现的样子。第一个 ^V 作为引用第二个 ^V 的字符: 这是
        因为 :ab 命令使用 ^V 作为它自己的引用字符，以便你能在缩写中包含被引用
        的空白字符或 | 字符。:ab 命令对 ^[ 字符并不做特殊的事情，所以它不需要
        被引用。(尽管引用也没有害处；因而输入 7 个 [8 个不行！] ^V 也会工
        作。)

被保存为:  esc     ^V^[

        解析后，该缩写的简短形式 ("esc") 和扩展形式 (两字符 "^V^[") 被保存在缩
        写表中。如果输入不带参数的 :ab 命令，这是该缩写被显示的形式。

        然后当用户输入单词 "esc" 而扩展该缩写时，扩展形式服从和一般键盘输入同
        样形式的 ^V 解释。所以 ^V 保护 ^[ 字符不被解释为 "退出插入模式" 的字
        符，而把 ^[ 插入到文本里。

扩展为: ^[

[Steve Kirkendall 提供示例]

</section><hr class="doubleline" /><section class=inner>
<h4>3. 局部映射和函数                               <b class="vimtag"> <a name="script-local">script-local</a> </b></h4>
当使用多个 Vim 脚本文件时，一个脚本和另一个脚本使用同样名字的映射和函数是危险
的。为了避免这种情况，它们可以局部在脚本。

                                                <b class="vimtag"> <a name="%3CSID%3E">&lt;SID&gt;</a> </b> <b class="vimtag"> <a name="%3CSNR%3E">&lt;SNR&gt;</a> </b> <b class="vimtag"> <a name="E81">E81</a> </b>
字串 "<code class="special">&lt;SID&gt;</code>" 能用于映射或菜单。这要求 <a href="options.html#'cpoptions'">'cpoptions'</a> 中没有 '&lt;' 标志位。
   当执行映射命令时，Vim 将把 "<code class="special">&lt;SID&gt;</code>" 替换成特殊键码 <code class="special">&lt;SNR&gt;</code>，后跟一个每个脚本唯
一的数字编号，和一个下划线。例如: 
<code class="example">        :map &lt;SID&gt;Add</code>
会定义一个映射 "<code class="special">&lt;SNR&gt;</code>23_Add"。

在脚本中定义函数的时候，可以在名字的前面用一个 "s:" 来使它局部于脚本 ( <a href="vim9.html#Vim9">Vim9</a> 
脚本里没有前缀的函数也是局部于脚本的)。但当一个映射在脚本外面被执行时，它不知
道它引用的局部函数在哪个脚本中被定义。为了避免这种情况，应使用 "<code class="special">&lt;SID&gt;</code>" 来代替
"s:"。映射也做同样的变换。这使得在映射里可以定义函数调用。

局部函数执行时，它在定义脚本的上下文中运行。这意味着，它定义的新函数和映射也可
以使用 "s:" 或 "<code class="special">&lt;SID&gt;</code>"，并且使用和函数本身定义时相同的唯一数字编号。此外，也能
用 "s:var" 脚本局部变量。

执行自动命令或用户命令时，它在定义脚本的上下文中运行。这使得该命令可以调用局部
函数或者使用局部映射。

要在不能正确展开 <code class="special">&lt;SID&gt;</code> 的场合下使用其值，可用 expand() 函数: 
<code class="example">        let &amp;includexpr = expand('&lt;SID&gt;') .. 'My_includeexpr()'</code>
<code class="example"></code>
除此以外，在脚本上下文之外使用 "<code class="special">&lt;SID&gt;</code>" 是错误的。

如果你需要在一个复杂的脚本中取得脚本的数字编号，使用此函数: 
<code class="example">        function s:ScriptNumber()</code>
<code class="example">          return matchstr(expand('&lt;SID&gt;'), '&lt;SNR&gt;\zs\d\+\ze_')</code>
<code class="example">        endfun</code>
<code class="example"></code>
列出函数和映射时会显示 "<code class="special">&lt;SNR&gt;</code>"。可以用来它们在哪里被定义。

命令  <a href="repeat.html#:scriptnames">:scriptnames</a>  可以用来查看哪些脚本已经被读入以及它们的 <code class="special">&lt;SNR&gt;</code> 数字编号。

这些都是 <code class="notvi">{仅当编译时加入  <a href="various.html#+eval">+eval</a>  特性才有效}</code>。

</section><hr class="doubleline" /><section class=inner>
<h4>4. 用户定义的命令                               <b class="vimtag"> <a name="user-commands">user-commands</a> </b></h4>
可以定义你自己的 Ex 命令。用户自定义命令可以和内建命令一样运行 (它可以有范围或
参数，参数可以是自动补全的文件名或缓冲区名，等等)，除了当该命令执行时，它会被
转换成一个普通的 Ex 命令然后再被执行以外。

对于初学者来说: 参考用户手册中的  <a href="usr_40.html#40.2">40.2</a>  。

                                        <b class="vimtag"> <a name="E183">E183</a> </b> <b class="vimtag"> <a name="E841">E841</a> </b> <b class="vimtag"> <a name="user-cmd-ambiguous">user-cmd-ambiguous</a> </b>
所有用户定义的命令都必须以大写字母开头，来避免与内建命令的冲突。以下内建命令是
例外:
        :Next
        :X
它们不能用于用户自定义命令。":Print" 也是已定义的命令，但已废弃，可以被覆盖。

用户命令的其它字符可以是大写字母，小写字母或数字。当使用数字时，小心会和其它以
数字作为参数的命令混淆。例如，命令 ":Cc2" 可能是不带参数的用户命令 ":Cc2"，也
可能是参数为 "2" 的命令 "Cc"。建议在命令名和参数之间放置一个空格来避免这些问
题。

当使用一个用户定义的命令时，该命令可以缩写。但是，如果缩写不唯一，会发生错误。
此外，内建命令总是优先执行。

例如: 
<code class="example">        :command Rename ..。</code>
<code class="example">        :command Renumber ..。</code>
<code class="example">        :Rena                           " 意味着 "Rename"</code>
<code class="example">        :Renu                           " 意味着 "Renumber"</code>
<code class="example">        :Ren                            " 错误 - 有二义性</code>
<code class="example">        :command Paste ..。</code>
<code class="example">        :P                              " 内建的 :Print</code>
<code class="example"></code>
建议在脚本中使用用户自定义命令的全名。

:com[mand]                                              <b class="vimtag"> <a name=":com">:com</a> </b> <b class="vimtag"> <a name=":command">:command</a> </b>
                        列出所有用户自定义命令。在列出命令时，
                        首栏的字符表示
                            !   命令有 -bang 属性
                            "   命令有 -register 属性
                            |   命令有 -bar 属性
                            b   命令局部于当前缓冲区
                        (下面给出属性的详细描述)
                        此列表可用  <a href="various.html#:filter">:filter</a>  命令过滤，例如，要列出所有名字带
                        "Pyth" 的命令: 
<code class="example">                                filter Pyth command</code>
<code class="example"></code>
:com[mand] <code class="special">{cmd}</code>        列出以 <code class="special">{cmd}</code> 开头的用户命令

                                                        <b class="vimtag"> <a name=":command-verbose">:command-verbose</a> </b>
如果 <a href="options.html#'verbose'">'verbose'</a> 非零，命令列出的同时显示它最近定义的位置和补全参数。例如: 
<code class="example"></code>
<code class="example">    :verbose command TOhtml</code>
<code class="section">        Name        Args Range Complete  Definition </code>
<code class="section">        TOhtml      0    %               :call Convert2HTML(<code class="special">&lt;line1&gt;</code>, <code class="special">&lt;line2&gt;</code>) </code>
<code class="section">            Last set from /usr/share/vim/vim-7.0/plugin/tohtml.vim </code>

 <a href="various.html#:verbose-cmd">:verbose-cmd</a>  介绍详情。

                                                        <b class="vimtag"> <a name="E174">E174</a> </b> <b class="vimtag"> <a name="E182">E182</a> </b>
:com[mand][!] [<code class="special">{attr}</code>...] <code class="special">{cmd}</code> <code class="special">{repl}</code>
                        定义一个用户命令。命令的名字是 <code class="special">{cmd}</code>，而替换的文本是
                        <code class="special">{repl}</code>。该命令的属性 (参考下面) 是 <code class="special">{attr}</code>。如果该命令
                        已存在，报错，除非已经指定了一个 !，这种情况下命令被重
                        定义。
                        有一个特例: 再次执行脚本时，该脚本中之前定义的命令会悄
                        然地被替代。

:delc[ommand] <code class="special">{cmd}</code>                             <b class="vimtag"> <a name=":delc">:delc</a> </b> <b class="vimtag"> <a name=":delcommand">:delcommand</a> </b> <b class="vimtag"> <a name="E184">E184</a> </b>
                        删除用户定义命令 <code class="special">{cmd}</code>。
                        列出命令时不允许使用，如在定时器回调中。 <b class="vimtag"> <a name="E1311">E1311</a> </b>

:delc[ommand] -buffer <code class="special">{cmd}</code>                                     <b class="vimtag"> <a name="E1237">E1237</a> </b>
                        删除为当前缓冲区定义的用户定义命令 <code class="special">{cmd}</code>。

:comc[lear]                                             <b class="vimtag"> <a name=":comc">:comc</a> </b> <b class="vimtag"> <a name=":comclear">:comclear</a> </b>
                        删除所有用户定义命令。

<code class="section">命令属性 </code>
                                                        <b class="vimtag"> <a name="command-attributes">command-attributes</a> </b>
Vim 和任何其它 Ex 命令一样对待用户自定义命令。它能有参数，也可以指定范围。参数
可以进行文件名，缓冲区等补全。具体的工作方式取决于命令的属性，属性在命令被定义
时被指定。

属性可分四大类: 参数处理、补全行为、范围处理和特殊情况。下面分类描述之。

<code class="section">参数处理 </code>
                                                <b class="vimtag"> <a name="E175">E175</a> </b> <b class="vimtag"> <a name="E176">E176</a> </b> <b class="vimtag"> <a name=":command-nargs">:command-nargs</a> </b>

缺省时，用户自定义命令不接受参数 (如果使用了任何参数会报错)。但通过使用 -nargs
属性可以允许命令接受参数。有效的值为:

        -nargs=0    不允许有参数 (缺省情况)
        -nargs=1    要求一个参数，包括空格
        -nargs=*    允许任何数目的参数 (0，1 或更多)，以空格分隔
        -nargs=?    允许 0 或 1 个参数
        -nargs=+    必需给出参数，但是数目任意

此上下文中，(未转义的) 空格或制表用来分隔参数，除非指定只有一个参数，此时空格
认为是参数的一部分。

<code class="note">注意</code> 参数被作为文本使用，不是表达式。特别是，"s:var" 会使用定义命令的脚本的局
部变量，不是执行时的！例如:
    script1.vim: 
<code class="example">        :let s:error = "None"</code>
<code class="example">        :command -nargs=1 Error echoerr &lt;args&gt;</code>
    script2.vim: 
<code class="example">        :source script1.vim</code>
<code class="example">        :let s:error = "Wrong!"</code>
<code class="example">        :Error s:error</code>
执行 script2.vim 会回显 "None"，不是你想要的！解决方法可以通过调用函数实现。

<code class="section">自动补全行为 </code>
                                <b class="vimtag"> <a name=":command-completion">:command-completion</a> </b> <b class="vimtag"> <a name="E179">E179</a> </b> <b class="vimtag"> <a name="E180">E180</a> </b> <b class="vimtag"> <a name="E181">E181</a> </b>
                                <b class="vimtag"> <a name=":command-complete">:command-complete</a> </b>
缺省时，用户定义命令的参数不进行自动补全。但是，通过指定以下的一个或多个属性
后，参数可以进行自动补全:

        -complete=arglist       参数列表中的文件名
        -complete=augroup       自动命令组
        -complete=buffer        缓冲区名
        -complete=behave        :behave 子选项
        -complete=color         颜色方案
        -complete=command       Ex 命令 (及其参数)
        -complete=compiler      编译器
        -complete=cscope         <a href="if_cscop.html#:cscope">:cscope</a>  子选项
        -complete=dir           目录名
        -complete=environment   环境变量名
        -complete=event         自动命令事件
        -complete=expression    Vim 表达式
        -complete=file          文件和目录名
        -complete=file_in_path   <a href="options.html#'path'">'path'</a>  中的文件和目录名
        -complete=filetype      文件类型名  <a href="options.html#'filetype'">'filetype'</a> 
        -complete=function      函数名
        -complete=help          帮助主题
        -complete=highlight     高亮组
        -complete=history        <a href="cmdline.html#:history">:history</a>  子选项
        -complete=locale        locale 名 (和 locale -a 给出的相同)
        -complete=mapclear      缓冲区参数
        -complete=mapping       映射名
        -complete=menu          菜单
        -complete=messages       <a href="message.html#:messages">:messages</a>  子选项
        -complete=option        选项
        -complete=packadd       可选包  <a href="repeat.html#pack-add">pack-add</a>  名
        -complete=shellcmd      外壳命令
        -complete=sign           <a href="sign.html#:sign">:sign</a>  子选项
        -complete=syntax        语法文件名  <a href="options.html#'syntax'">'syntax'</a> 
        -complete=syntime        <a href="syntax.html#:syntime">:syntime</a>  子选项
        -complete=tag           标签
        -complete=tag_listfiles 标签，但敲入 <code class="keystroke">CTRL-D</code> 时显示文件名
        -complete=user          用户名
        -complete=var           用户变量
        -complete=custom,<code class="special">{func}</code> 用户定制的自动补全，通过 <code class="special">{func}</code> 来定义
        -complete=customlist,<code class="special">{func}</code> 用户定制的自动补全，通过 <code class="special">{func}</code> 来定义

如果指定了补全但没有什么可补全的 (-nargs=0，缺省)，报错 <b class="vimtag"> <a name="E1208">E1208</a> </b> 。
<code class="note">备注</code>: 部分补全方法可能会扩展环境变量。


<code class="section">用户定制的自动补全 </code>
                                <b class="vimtag"> <a name=":command-completion-custom">:command-completion-custom</a> </b>
                                <b class="vimtag"> <a name=":command-completion-customlist">:command-completion-customlist</a> </b> <b class="vimtag"> <a name="E467">E467</a> </b> <b class="vimtag"> <a name="E468">E468</a> </b>
通过 "custom,<code class="special">{func}</code>" 或 "customlist,<code class="special">{func}</code>" 自动补全参数可以定义定制的自动补全
方案。其中 <code class="special">{func}</code> 是有如下声明的函数:

        :function <code class="special">{func}</code>(ArgLead，CmdLine，CursorPos)

该函数不需要使用所有的这些参数，它应该提供自动补全候选作为返回值，

对于 "custom" 参数，函数应该返回字符串，每行一个候选，用换行符分隔。
                                                        <b class="vimtag"> <a name="E1303">E1303</a> </b>
对于 "customlist" 参数，函数应该返回 Vim 列表形式的补全候选。忽略列表里的非字
符串项目。

该函数的参数是:
        ArgLead         当前自动补全的前导参数
        CmdLine         完整的命令行
        CursorPos       里面的光标位置 (字节位置)
该函数可能要根据这些来判别上下文。对 "custom" 参数，它无须用 ArgLead (里面的隐
式规则) 来过滤候选。在函数返回时 Vim 将用它的正则表达式引擎来进行过滤，这种方
式在大多数情况下效率更高。如果 <a href="options.html#'wildoptions'">'wildoptions'</a> 包含 "fuzzy"，候选会用
 <a href="pattern.html#fuzzy-matching">fuzzy-matching</a>  过滤。对于 "customlist" 参数，Vim 不会过滤返回的补全候选，用
户提供的函数应该自己过滤候选。

以下的例子为列出 Finger 命令的用户名 
<code class="example">    :com -complete=custom,ListUsers -nargs=1 Finger !finger &lt;args&gt;</code>
<code class="example">    :fun ListUsers(A,L,P)</code>
<code class="example">    :    return system("cut -d: -f1 /etc/passwd")</code>
<code class="example">    :endfun</code>
<code class="example"></code>
下例从 <a href="options.html#'path'">'path'</a> 选项指定的目录补全文件名: 
<code class="example">    :com -nargs=1 -bang -complete=customlist,EditFileComplete</code>
<code class="example">                        \ EditFile edit&lt;bang&gt; &lt;args&gt;</code>
<code class="example">    :fun EditFileComplete(A,L,P)</code>
<code class="example">    :    return split(globpath(&amp;path, a:A), "\n")</code>
<code class="example">    :endfun</code>

此例不适用于带空格的文件名！


<code class="section">范围处理 </code>
                                <b class="vimtag"> <a name="E177">E177</a> </b> <b class="vimtag"> <a name="E178">E178</a> </b> <b class="vimtag"> <a name=":command-range">:command-range</a> </b> <b class="vimtag"> <a name=":command-count">:command-count</a> </b>
缺省时，用户定义的命令不接受一个行号范围。不过，可以使命令接受一个范围 (-range
属性)，或者接受一个任意的数量值，该数量可以出现在指定行号的位置 (-range=N，类
似于  <a href="windows.html#:split">:split</a>  命令的风格)，也可以来自一个 "count" 参数 (-count=N，类似于
 <a href="editing.html#:Next">:Next</a>  命令的风格)。此时计数可以用  <a href="map.html#%3Ccount%3E">&lt;count&gt;</a>  从参数里得到。

可能的属性有:

        -range      允许使用范围，缺省为当前行
        -range=%    允许使用范围，缺省是整个文件 (1,$)
        -range=N    出现在行号位置的一个数量 (缺省是 N) (类似于  <a href="windows.html#:split">:split</a> )；允
                    许行号为零。
        -count=N    出现在行号位置或者作为首个参数的一个数量 (缺省是 N) (类似
                    于  <a href="editing.html#:Next">:Next</a> )。
        -count      同 -count=0

<code class="note">注意</code> -range=N 和 -count=N 是互斥的，只应该指定其中的一个。

                                        <b class="vimtag"> <a name=":command-addr">:command-addr</a> </b>
范围中的特殊字符如 .、$ 或 % 缺省对应当前行、末行和整个缓冲区，但可使之对应参
数列表、(已载入的) 缓冲区、窗口或标签页。

可能值有 (第二列是列表使用的短名):
    -addr=lines                 行的范围 (这是缺省)
    -addr=arguments       arg   参数的范围
    -addr=buffers         buf   缓冲区的范围 (也包括未载入的缓冲区)
    -addr=loaded_buffers  load  载入缓冲区的范围
    -addr=windows         win   窗口的范围
    -addr=tabs            tab   标签页的范围
    -addr=quickfix        qf    快速修复项的范围
    -addr=other           ?     其它范围；可用 "."、"$" 和 "%" 还有 "lines"
                                (这是 -count 的缺省)


<code class="section">特殊情况 </code>
                                        <b class="vimtag"> <a name=":command-bang">:command-bang</a> </b> <b class="vimtag"> <a name=":command-bar">:command-bar</a> </b>
                                        <b class="vimtag"> <a name=":command-register">:command-register</a> </b> <b class="vimtag"> <a name=":command-buffer">:command-buffer</a> </b>
                                        <b class="vimtag"> <a name=":command-keepscript">:command-keepscript</a> </b>
有如下特殊情况:

        -bang       这些命令可以使用一个 ! 修饰符 (和 :q 或 :w 类似)
        -bar        这些命令可以跟随一个 "|" 和其它命令。那么命令参数中就
                    不允许有 "|" 。用一个 " 可以开始一个注释。
        -register   给这些命令的第一个参数可以是一个可选的寄存器名
                    (和 :del，:put，:yank 类似)。
        -buffer     这些命令仅在当前缓冲区里有效。
        -keepscript 详细 (verbose) 消息不采用用户命令定义所在的位置，而是用户
                    命令被调用的位置。

-count 和 -register 属性的情况，如果提供了可选的参数，它会被从参数列表中删除，
并且和替换文本分别处理。
<code class="note">注意</code> 这些参数可以简写，但这是已淘汰的功能，新脚本里请用全名。

<code class="section">替换文本 </code>
                                                        <b class="vimtag"> <a name=":command-repl">:command-repl</a> </b>
<code class="special">{repl}</code> 参数通常是一个长字符串，可能用 "|" 来分隔命令。参数为 "{" 时是特例，此
时使用后续直到以 "}" 开始的行为止的所有行，应用  <a href="vim9.html#Vim9">Vim9</a>  语法。示例: 
<code class="example">        :command MyCommand {</code>
<code class="example">                echo 'hello'</code>
<code class="example">                g:calledMyCommand = true</code>
<code class="example">            }</code>
                                                        <b class="vimtag"> <a name="E1231">E1231</a> </b>
"{" 之前必须有空白。不支持嵌套，不能使用内联函数。对 "|" 可能在参数里出现的命
令，如带表达式参数的命令，不能后跟 "|" 和其他命令。

对用户自定义命令的替换文本 <code class="special">{repl}</code> 进行扫描，找到使用 &lt;...&gt; 记法的特殊转义序列。
转义序列被命令行输入提供的值替换，其它文本不变。最终字符串被作为 Ex 命令来执
行。要避免替换，使用 <code class="special">&lt;lt&gt;</code> 代替初始的 &lt;。这样，要按本义包含 "<code class="special">&lt;bang&gt;</code>"，请使用
"<code class="special">&lt;lt&gt;</code>bang&gt;"。

有效的转义序列有

                                                <b class="vimtag"> <a name="%3Cline1%3E">&lt;line1&gt;</a> </b>
        <code class="special">&lt;line1&gt;</code> 命令处理范围的开始行。
                                                <b class="vimtag"> <a name="%3Cline2%3E">&lt;line2&gt;</a> </b>
        <code class="special">&lt;line2&gt;</code> 命令处理范围的末尾行。
                                                <b class="vimtag"> <a name="%3Crange%3E">&lt;range&gt;</a> </b>
        <code class="special">&lt;range&gt;</code> 命令处理范围的项目数: 0、1 或 2
                                                <b class="vimtag"> <a name="%3Ccount%3E">&lt;count&gt;</a> </b>
        <code class="special">&lt;count&gt;</code> 提供的数量 (在 '-range' 和 '-count' 属性中描述)。
                                                <b class="vimtag"> <a name="%3Cbang%3E">&lt;bang&gt;</a> </b>
        <code class="special">&lt;bang&gt;</code>  (参考 '-bang' 属性) 如果命令执行时带了 ! 修饰符，扩展为 !，否
                则什么也不扩展。
                                        <b class="vimtag"> <a name="%3Cmods%3E">&lt;mods&gt;</a> </b> <b class="vimtag"> <a name="%3Cq-mods%3E">&lt;q-mods&gt;</a> </b> <b class="vimtag"> <a name=":command-modifiers">:command-modifiers</a> </b>
        <code class="special">&lt;mods&gt;</code>  如果指定，命令修饰符。否则不扩展。支持以下修饰符
                 <a href="windows.html#:aboveleft">:aboveleft</a> 、 <a href="windows.html#:belowright">:belowright</a> 、 <a href="windows.html#:botright">:botright</a> 、 <a href="editing.html#:browse">:browse</a> 、
                 <a href="editing.html#:confirm">:confirm</a> 、 <a href="windows.html#:hide">:hide</a> 、 <a href="windows.html#:horizontal">:horizontal</a> 、 <a href="editing.html#:keepalt">:keepalt</a> 、 <a href="motion.html#:keepjumps">:keepjumps</a> 、
                 <a href="motion.html#:keepmarks">:keepmarks</a> 、 <a href="cmdline.html#:keeppatterns">:keeppatterns</a> 、 <a href="windows.html#:leftabove">:leftabove</a> 、 <a href="motion.html#:lockmarks">:lockmarks</a> 、
                 <a href="autocmd.html#:noautocmd">:noautocmd</a> 、 <a href="recover.html#:noswapfile">:noswapfile</a> 、 <a href="windows.html#:rightbelow">:rightbelow</a> 、 <a href="eval.html#:sandbox">:sandbox</a> 、
                 <a href="various.html#:silent">:silent</a> 、 <a href="tabpage.html#:tab">:tab</a> 、 <a href="windows.html#:topleft">:topleft</a> 、 <a href="various.html#:unsilent">:unsilent</a> 、 <a href="various.html#:verbose">:verbose</a>  和
                 <a href="windows.html#:vertical">:vertical</a> 。
                <code class="note">注意</code> 不支持  <a href="various.html#:filter">:filter</a> 。
                示例: 
<code class="example">                    command! -nargs=+ -complete=file MyEdit</code>
<code class="example">                                \ for f in expand(&lt;q-args&gt;, 0, 1) |</code>
<code class="example">                                \ exe '&lt;mods&gt; split ' .. f |</code>
<code class="example">                                \ endfor</code>
<code class="example"></code>
<code class="example">                    function! SpecialEdit(files, mods)</code>
<code class="example">                        for f in expand(a:files, 0, 1)</code>
<code class="example">                            exe a:mods .. ' split ' .. f</code>
<code class="example">                        endfor</code>
<code class="example">                    endfunction</code>
<code class="example">                    command! -nargs=+ -complete=file Sedit</code>
<code class="example">                                \ call SpecialEdit(&lt;q-args&gt;, &lt;q-mods&gt;)</code>

                                                <b class="vimtag"> <a name="%3Creg%3E">&lt;reg&gt;</a> </b> <b class="vimtag"> <a name="%3Cregister%3E">&lt;register&gt;</a> </b>
        <code class="special">&lt;reg&gt;</code>   (参考 '-register' 属性) 如果命令行上指定，可选的寄存器名。否则
                什么也不扩展。<code class="special">&lt;register&gt;</code> 是它的一个同义词。
                                                <b class="vimtag"> <a name="%3Cargs%3E">&lt;args&gt;</a> </b>
        <code class="special">&lt;args&gt;</code>  命令的参数，和实际提供的完全相同 (但正如上面提到过的，数量或寄
                存器会消耗若干参数，它们不再是 <code class="special">&lt;args&gt;</code> 的一部分)。
        <code class="special">&lt;lt&gt;</code>    一个单独的 '&lt;' (小于号) 字符。在扩展中可用于使以上转义序列按本
                义出现。例如，要获得 <code class="special">&lt;bang&gt;</code>，使用 <code class="special">&lt;lt&gt;</code>bang&gt;。

                                                        <b class="vimtag"> <a name="%3Cq-args%3E">&lt;q-args&gt;</a> </b>
如果一个转义序列的最前两个字符是 "q-" (例如，<code class="special">&lt;q-args&gt;</code>) 那么该值用引号括起，使
之在表达式里使用时成为合法的值。这种方式把参数当做单个值。如果没有参数，
<code class="special">&lt;q-args&gt;</code> 是空字符串。见下  <a href="map.html#q-args-example">q-args-example</a> 。
                                                        <b class="vimtag"> <a name="%3Cf-args%3E">&lt;f-args&gt;</a> </b>
要允许命令把参数传送给用户定义的函数，有一种特殊的形式 <code class="special">&lt;f-args&gt;</code> ("function
args"，函数参数)。它在空格和制表处分割命令行参数，每个参数分别用引号括起，然后
把 <code class="special">&lt;f-args&gt;</code> 序列替换为括起参数用逗号分隔的列表。参考下面的 Mycmd 示例。没有参
数时，<code class="special">&lt;f-args&gt;</code> 被删除。
   要在 <code class="special">&lt;f-args&gt;</code> 的参数中嵌入空白字符，在前面加上反斜杠。<code class="special">&lt;f-args&gt;</code> 把每对反斜杠
(\\) 用单个反斜杠替代。反斜杠后如跟非空白或反斜杠字符，保持不变。另见下
 <a href="map.html#f-args-example">f-args-example</a> 。总览如下:

<code class="section">        命令               <code class="special">&lt;f-args&gt;</code> </code>
        XX ab              <code class="badlink">'ab'</code>
        XX a\b             'a\b'
        XX a\ b            'a b'
        XX a\  b           'a ', 'b'
        XX a\\b            'a\b'
        XX a\\ b           'a\', 'b'
        XX a\\\b           'a\\b'
        XX a\\\ b          'a\ b'
        XX a\\\\b          'a\\b'
        XX a\\\\ b         'a\\', 'b'

用户命令的示例: 
<code class="example"></code>
<code class="example">   " 删除从这里到末尾的所有东西</code>
<code class="example">   :com Ddel +,$d</code>
<code class="example"></code>
<code class="example">   " 把当前缓冲区改名</code>
<code class="example">   :com -nargs=1 -bang -complete=file Ren f &lt;args&gt;|w&lt;bang&gt;</code>
<code class="example"></code>
<code class="example">   " 用一个文件的内容来替换某个范围内的内容</code>
<code class="example">   " (请用一行输入本命令)</code>
<code class="example">   :com -range -nargs=1 -complete=file</code>
<code class="example">         Replace &lt;line1&gt;-pu_|&lt;line1&gt;,&lt;line2&gt;d|r &lt;args&gt;|&lt;line1&gt;d</code>
<code class="example"></code>
<code class="example">   " 计算范围内的行数</code>
<code class="example">   :com! -range -nargs=0 Lines  echo &lt;line2&gt; - &lt;line1&gt; + 1 "lines"</code>
<code class="example"></code>
                                                <b class="vimtag"> <a name="f-args-example">f-args-example</a> </b>
调用一个用户函数 (<code class="special">&lt;f-args&gt;</code> 的示例) 
<code class="example">   :com -nargs=* Mycmd call Myfunc(&lt;f-args&gt;)</code>
<code class="example"></code>
当执行: 
<code class="example">        :Mycmd arg1 arg2</code>
时，它将调用: 
<code class="example">        :call Myfunc("arg1","arg2")</code>
<code class="example"></code>
                                                <b class="vimtag"> <a name="q-args-example">q-args-example</a> </b>
一个更实用的例子: 
<code class="example">   :function Allargs(command)</code>
<code class="example">   :    let i = 0</code>
<code class="example">   :    while i &lt; argc()</code>
<code class="example">   :       if filereadable(argv(i))</code>
<code class="example">   :        execute "e " .. argv(i)</code>
<code class="example">   :         execute a:command</code>
<code class="example">   :      endif</code>
<code class="example">   :      let i = i + 1</code>
<code class="example">   :   endwhile</code>
<code class="example">   :endfunction</code>
<code class="example">   :command -nargs=+ -complete=command Allargs call Allargs(&lt;q-args&gt;)</code>
<code class="example"></code>
命令 Allargs 接受任意 Vim 命令作为参数并在参数列表里的所有文件上执行。使用示例
(<code class="note">注意</code>使用 "e" 标志位来忽略错误，以及用 "update" 命令来刷新修改过的缓冲区):
        :Allargs %s/foo/bar/ge|update
它将调用: 
<code class="example">        :call Allargs("%s/foo/bar/ge|update")</code>

如果命令在 Vim9 脚本中定义 ( <a href="repeat.html#:vim9script">:vim9script</a>  开始的脚本并出现在  <a href="vim9.html#:def">:def</a>  函数中)，
以 Vim9 脚本模式执行 <code class="special">{repl}</code>。这只取决于命令定义的位置，而不是它被调用的位置。

在脚本里定义用户命令时，它可以调用局部于脚本中的函数和使用局部于脚本的映射。用
户调用用户命令时，该命令将运行在定义它的脚本的上下文里，如果一个命令中使用了
 <a href="map.html#%3CSID%3E">&lt;SID&gt;</a> ，这一点很重要。

 vim:tw=78:ts=8:noet:ft=help:norl:
</section>
</article>
<footer>
Generated by vim2html
</footer>
</body>
</html>
